• Welcome to Dark Bit Factory & Gravity.
 

klystrack!

Started by n00bstar, May 31, 2012

Previous topic - Next topic

0 Members and 0 Guests are viewing this topic.

n00bstar

For some reason, a few week backs, I decided to check what was happening in the world of trackers. I've graduated from trackers to actual 'real' studio stuff years ago, but tracking will still always have a big warm fluffy place in my heart. So I've found the usual assortment of softwares, from clones of FT2 and IT to trackers that support all the VSTs in the world and dice your veggies and takes your kids to school and all that. All in all, it was a fairly disappointing experience. No scene spirit anywhere.. just VSTs and commercial products. That is, until I added the magic word to my Googling: Chiptune!

On top of a long list of only 1 item came: klystrack!

So heading over there and downloading this gizmo, I fell in love. The scene-cred is very high with this one, it looks like it was made in the 90s, it's fully open source, great developer support and a very comprehensive manual/wiki.

Those of you who remember AHX on the Amiga will be riiight at home with Klystrack, it takes most of its cues from it down to the sequence editor using floating patterns of variable lengths etc.

There's a library for it should you want to use the synth engine for your own products or to playback .KT tracks.

If you've read this far and haven't yet googled it and downloaded it, then lemme at least do the first step to help you out: http://code.google.com/p/klystrack/


energy

Very good work. :clap:
Is there a replay routine available?
coding: jwasm,masm
hobby: www.scd2003.de

Pot Noodle

Good info n00bstar, Thanks for that I am glad you found the Amiga scene spirit you were looking for.  :goodpost:

n00bstar

@Energy, yes there is! Well... kind of, the code is there and the dev gives you all the info needed to compile your own. From what little I've toyed with the code, it is extremely efficient and has almost no CPU hit to speak of. Seeing as it takes me 8 hours of hard work and case of red bull to put a single sinescroller on screen, I don't think I'll be the one compiling it into a nifty little lib, but if anyone wants to give it a go (make me a blitz wrapper purdy pleez?) I will make music for all your projects out of sheer gratitude :D

benny!

Looks awesome. Thanks for sharing!
[ mycroBLOG - POUET :: whatever keeps us longing - for another breath of air - is getting rare ]

Challenge Trophies Won:

zawran

I took a look at getting it to work with Bmax, and here is some code for you:


'
' load the KSND DLL into memory
'
Const KSND_DLL:String = "ksnd.dll"
Global g_hndDLL:Int
g_hndDLL = loadlibrarya(KSND_DLL)
If g_hndDLL = Null Or g_hndDLL = 0 Then
RuntimeError "Unable to find the file: "+KSND_DLL
End If

Private
' player calls
Global KSND_CreatePlayer:Byte Ptr(samplerate:Int)"Win32" = GetProcAddress(g_hndDLL,"KSND_CreatePlayer")
Global KSND_FreePlayer(kplayer:Byte Ptr)"Win32" = GetProcAddress(g_hndDLL,"KSND_FreePlayer")
Global KSND_PlaySong(kplayer:Byte Ptr,ksong:Byte Ptr,position:Int)"Win32" = GetProcAddress(g_hndDLL,"KSND_PlaySong")
Global KSND_Stop(kplayer:Byte Ptr)"Win32" = GetProcAddress(g_hndDLL,"KSND_Stop")
Global KSND_Pause(kplayer:Byte Ptr,state:Int)"Win32" = GetProcAddress(g_hndDLL,"KSND_Pause")
Global KSND_GetPlayPosition:Int(kplayer:Byte Ptr)"Win32" = GetProcAddress(g_hndDLL,"KSND_GetPlayPosition")
Global KSND_SetVolume(kplayer:Byte Ptr,volume:Int)"Win32" = GetProcAddress(g_hndDLL,"KSND_SetVolume")
' song calls
Global KSND_LoadSong:Byte Ptr(kplayer:Byte Ptr,path:Byte Ptr)"Win32" = GetProcAddress(g_hndDLL,"KSND_LoadSong")
Global KSND_LoadSongFromMemory:Byte Ptr(kplayer:Byte Ptr,mem:Byte Ptr,length:Int)"Win32" = GetProcAddress(g_hndDLL,"KSND_LoadSongFromMemory")
Global KSND_FreeSong(ksong:Byte Ptr)"Win32" = GetProcAddress(g_hndDLL,"KSND_FreeSong")
Global KSND_GetSongLength:Int(ksong:Byte Ptr)"Win32" = GetProcAddress(g_hndDLL,"KSND_GetSongLength")
Public

Type TKSND
Field player:Byte Ptr ' handle to active player
Field song:Byte Ptr ' handle to currently playing song

Function init:TKSND(samplerate:Int)
Local tmp:TKSND = New TKSND
tmp.player = KSND_CreatePlayer(samplerate)
Return tmp
End Function

' Player methods

Method play(position:Int=0)
KSND_PlaySong(Self.player,Self.song,position)
End Method

Method pause(state:Int=0)
' 1 = pause, 0 = continue
KSND_Pause(Self.player,state)
End Method

Method stop()
KSND_Stop(Self.player)
End Method

Method free()
KSND_FreePlayer(Self.player)
End Method

Method setVolume(volume:Int)
KSND_SetVolume(Self.player,volume)
End Method

Method getPlayPosition:Int()
Return KSND_GetPlayPosition(Self.player)
End Method

' Song methods

Method loadSong(path:String)
' check if a song is already loaded
If Self.song <> Null Then Self.freeSong()
Self.song = KSND_LoadSong(Self.player,path.ToCString())
If Self.song = Null Then
RuntimeError "Unable to load song: "+path
Else
Print "song loaded"
End If
End Method

Method loadSongFromMemory(mem:Byte Ptr,length:Int)
' check if a song is already loaded
If Self.song <> Null Then Self.freeSong()
Self.song = KSND_LoadSongFromMemory(Self.player,mem,length)
If Self.song = Null Then
RuntimeError "Unable to load song!"
Else
Print "song loaded"
End If
End Method

Method freeSong()
KSND_FreeSong(Self.song)
End Method

Method getSongLength:Int()
Return KSND_GetSongLength(Self.song)
End Method
End Type


And here is an example of using the above code:


SuperStrict
Incbin "obspatial.kt" ' this is for including the song in the exe

Include "TKSND.BMX"

Graphics 800,600


' prepare a player
Global music:TKSND = TKSND.init(44100)

' use this when loading song from bank
Global bk:TBank = LoadBank("incbin::obspatial.kt") ' this loads the song into a bank
music.loadSongFromMemory(LockBank(bk),BankSize(bk))
bk = Null

' use this when loading song from disc
'music.loadSong("obspatial.kt")

' play the music
music.play()

Global mute:Int = 0

While Not KeyHit(KEY_ESCAPE)
Cls
Local sl:Int = music.getSongLength()
Local pp:Int = music.getPlayPosition()
DrawText("Song Length: "+sl,8,8)
DrawText("Play Position: "+pp,8,24)
If mute = 1 Then DrawText("MUTED",8,48)
' check for pause/continue
If KeyHit(KEY_P) Then music.pause(1)
If KeyHit(KEY_C) Then music.pause(0)
' check for mute/unmute
If KeyHit(KEY_M) Then
mute = 1-mute
If mute = 0 Then
music.setVolume(100)
Else
music.setVolume(0)
End If
End If
Flip
Wend
music.freeSong()
music.free()
End


The known bugs are that the method for getting the length of the song returns a wrong number in release mode, but works correct in debug mode. I am not really sure where the problem lies, but since it is not something that will prevent people from using the klystrack tunes in their productions I figured that I might as well release the code already. I hope someone finds it useful. Remember to copy the ksnd.dll file to your project folder.

n00bstar

!!!!!!!!!!!

You rock sir. Tonight when you come home, your wife will be gold plated and your car will have spoilers on ALL FOUR SIDES. Damn right.

Now I have no choice, I have to switch to BMax! I was kinda of planning on it anyways (seeing as its s'posed to share a lot of syntax with Monkey) and this is a very good reason for it :)

But I'm at work and I only got b3d installed here. This is gonna be a long ass day before I get to play with this!

zawran

No problem, it was fun trying to get it to work.

Shockwave

Cool deed Zawran :) K+
Shockwave ^ Codigos
Challenge Trophies Won:

Rbz

Very nice little tracker!

I've made a Freebasic wrapper using klystrack static library, examples included.
Purebasic version can be also easily made ;)

Challenge Trophies Won:

jace_stknights

As fast as the light!  :clap: Rbz :clap:
Challenge Trophies Won:

zawran

Seeing that RBZ has made a wrapper for freebasic using the static library so that you do not have to have the dll file in the folder, I thought that I would give it a go at making the wrapper do the same for Bmax. And after some thinkering I managed to get it to work.

Here is the new type for the wrapper:


Private
Extern "Os"
Function KSND_CreatePlayer:Byte Ptr(samplerate:Int)"C"
Function KSND_FreePlayer(kplayer:Byte Ptr)"C"
Function KSND_PlaySong(kplayer:Byte Ptr,ksong:Byte Ptr,position:Int)"C"
Function KSND_Stop(kplayer:Byte Ptr)"C"
Function KSND_Pause(kplayer:Byte Ptr,state:Int)"C"
Function KSND_GetPlayPosition:Int(kplayer:Byte Ptr)"C"
Function KSND_SetVolume(kplayer:Byte Ptr,volume:Int)"C"
' song calls
Function KSND_LoadSong:Byte Ptr(kplayer:Byte Ptr,path:Byte Ptr)"C"
Function KSND_LoadSongFromMemory:Byte Ptr(kplayer:Byte Ptr,mem:Byte Ptr,length:Int)"C"
Function KSND_FreeSong(ksong:Byte Ptr)"C"
Function KSND_GetSongLength:Int(ksong:Byte Ptr)"C"
End Extern
Public

Type TKSND
Field player:Byte Ptr ' handle to active player
Field song:Byte Ptr ' handle to currently playing song

Function init:TKSND(samplerate:Int)
Local tmp:TKSND = New TKSND
tmp.player = KSND_CreatePlayer(samplerate)
Return tmp
End Function

' Player methods

Method play(position:Int=0)
KSND_PlaySong(Self.player,Self.song,position)
End Method

Method pause(state:Int=0)
' 1 = pause, 0 = continue
KSND_Pause(Self.player,state)
End Method

Method stop()
KSND_Stop(Self.player)
End Method

Method free()
KSND_FreePlayer(Self.player)
End Method

Method setVolume(volume:Int)
KSND_SetVolume(Self.player,volume)
End Method

Method getPlayPosition:Int()
Return KSND_GetPlayPosition(Self.player)
End Method

' Song methods

Method loadSong(path:String)
' check if a song is already loaded
If Self.song <> Null Then Self.freeSong()
Self.song = KSND_LoadSong(Self.player,path.ToCString())
If Self.song = Null Then
RuntimeError "Unable to load song: "+path
Else
Print "song loaded"
End If
End Method

Method loadSongFromMemory(mem:Byte Ptr,length:Int)
' check if a song is already loaded
If Self.song <> Null Then Self.freeSong()
Self.song = KSND_LoadSongFromMemory(Self.player,mem,length)
If Self.song = Null Then
RuntimeError "Unable to load song!"
Else
Print "song loaded"
End If
End Method

Method freeSong()
KSND_FreeSong(Self.song)
End Method

Method getSongLength:Int()
Return KSND_GetSongLength(Self.song)
End Method
End Type


And here is a new example to show how it is called:


SuperStrict
Import "-lksndstatic"

Incbin "Paranoimia (Suntronic).kt" ' this is for including the song in the exe

Include "TKSNDstatic.BMX"

Graphics 800,600


' prepare a player
Global music:TKSND = TKSND.init(44100)

' use this when loading song from bank
Global bk:TBank = LoadBank("incbin::Paranoimia (Suntronic).kt") ' this loads the song into a bank
music.loadSongFromMemory(LockBank(bk),BankSize(bk))
bk = Null

' use this when loading song from disc
'music.loadSong("obspatial.kt")

' play the music
music.play()

Global mute:Int = 0

While Not KeyHit(KEY_ESCAPE)
Cls
Local sl:Int = music.getSongLength()
Local pp:Int = music.getPlayPosition()
DrawText("Song Length: "+sl,8,8)
DrawText("Play Position: "+pp,8,24)
If mute = 1 Then DrawText("MUTED",8,48)
' check for pause/continue
If KeyHit(KEY_P) Then music.pause(1)
If KeyHit(KEY_C) Then music.pause(0)
' check for mute/unmute
If KeyHit(KEY_M) Then
mute = 1-mute
If mute = 0 Then
music.setVolume(100)
Else
music.setVolume(0)
End If
End If
Flip
Wend
music.freeSong()
music.free()
End


So instead of copying the dll file to your project folder, you copy the following file "libksndstatic.a" to the "lib" folder in your Bmax installation folder.

Using this version will pack the player code into your exe and you no longer need the dll file. Please note that new line <Import "-lksndstatic"> at the top of the example. You will have to have that line in the top of your project code along with what other imports you have. It is the line that loads the c library.

Pot Noodle

Well done guys, I don't think n00bstar will need all that Red Bull now!  :goodpost:

TinDragon

For the Bmax users, if you dont feel like copying the libksndstatic.a into your bmax lib folder and would rather have it in the projects folder (I know some people prefer this) then you can do so, just change the import line from
Import "-lksndstatic"
to
Import "libksndstatic.a"

Nice job on wrapping this player guys, now lets seem some of you creative types make some tunes in it :D

n00bstar

music?

three tracks included, free for all to use in dbf-related prods :)


padman

QuotePurebasic version can be also easily made ;)

Word. PB wrapper & example attached. ;D

I didn't do too much testing, but the main functions work on my WinXP machine...

Enjoy!


Challenge Trophies Won:

Shockwave

Shockwave ^ Codigos
Challenge Trophies Won:

Kirl

www.kirl.nl
Challenge Trophies Won:

n00bstar

Very good work people!

Yknow, I think that, with's you's people's permissions'ses of course, we should be contacting klystrack's author and have him host these wrappers alongside the software, it would certainly give a bigger incentive to interested parties who might not have the know how to wrap the lib and can't afford the real estate of downmixing to wav.

Also, I'm a man of my word, I re-extend the offer for one (1) free and personalized klystrack song to anyone who develops something for my favorite little tracker :)

jace_stknights

 :clap: well done Pad!
Challenge Trophies Won: