Recent

Author Topic: SoundTracker Player Library  (Read 2140 times)

Gigatron

  • Sr. Member
  • ****
  • Posts: 404
  • Amiga Rulez !!
    • Gigatron Shader Network Demo
SoundTracker Player Library
« on: February 12, 2026, 04:28:05 pm »
Ok ,

I've compiled this library for WindowsX64  to play old amiga modules , here is the list
of supported format hope it's working for all;

Source are from Christian Corti neoart .js and Flod 4.1 by roflOr some bugs are fixed , this was mentioned now !
https://github.com/rofl0r/c-flod

ULTIMATE_SOUNDTRACKER Tested
TJC_SOUNDTRACKER2        Tested
DOC_SOUNDTRACKER4       Tested
ULTIMATE SOuNDRACKER    Tested
MASTER_SOUNDTRACKER    Tested
DOC_SOUNDTRACKER9   
DOC_SOUNDTRACKER20   
SOUNDTRACKER23       
NOISETRACKER10      Tested
NOISETRACKER11      Tested 
PROTRACKER10         Tested
NOISETRACKER20      Tested
STARTREKKER         
PROTRACKER10C       Tested
PROTRACKER20         
PROTRACKER30       

But Xmplay.dll can play all those modules ? yes but it's for my personnal usage
to reduce the size of .dll to upload my demos on lazarus forum, only 83kb

7z compression was used for  project example and include 3 modules;

Have fun;
 
« Last Edit: February 12, 2026, 06:34:00 pm by Gigatron »
Coding faster than Light !

Gigatron

  • Sr. Member
  • ****
  • Posts: 404
  • Amiga Rulez !!
    • Gigatron Shader Network Demo
Re: SoundTracker Player Library
« Reply #1 on: February 14, 2026, 09:48:37 pm »
This library is now ok and updated with more methods ;

Finally splitted units to have audio part on SoundrackerAudio.pas the code is now
much clear; If you are in windows it's working with music if not the compilation working
but not music on linux or MacOS i think !

Regards

Code: Pascal  [Select][+][-]
  1. unit soundtracker_lib;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5.   Classes, SysUtils;
  6.  
  7. type
  8.   PStDecoder = Pointer;
  9.  
  10. // Create ... destroy
  11. function  soundtracker_decoder_new(): PStDecoder; cdecl; external 'Soundtracker.dll';
  12. procedure soundtracker_decoder_free(decoder: PStDecoder); cdecl; external 'Soundtracker.dll';
  13.  
  14. // Load  file
  15. function  soundtracker_decoder_init(decoder: PStDecoder; buffer: Pointer; bufferLen: NativeUInt): Integer; cdecl; external 'Soundtracker.dll';
  16.  
  17. // Fill buffer
  18. function  soundtracker_decoder_fillBuffer(decoder: PStDecoder; buffer: Pointer; bufferSize: Cardinal): Cardinal; cdecl; external 'Soundtracker.dll';
  19.  
  20. // play control
  21. procedure soundtracker_decoder_pause(decoder: PStDecoder); cdecl; external 'Soundtracker.dll';
  22. procedure soundtracker_decoder_resume(decoder: PStDecoder); cdecl; external 'Soundtracker.dll';
  23. procedure soundtracker_decoder_setLoop(decoder: PStDecoder; enabled: Integer); cdecl; external 'Soundtracker.dll';
  24. procedure soundtracker_decoder_rewind(decoder: PStDecoder); cdecl; external 'Soundtracker.dll';
  25. function  soundtracker_decoder_seek(decoder: PStDecoder; order: Integer): Integer; cdecl; external 'Soundtracker.dll';
  26.  
  27. // play state
  28. function  soundtracker_decoder_get_position(decoder: PStDecoder): Integer; cdecl; external 'Soundtracker.dll';  // order courant
  29. function  soundtracker_decoder_get_pattern(decoder: PStDecoder): Integer; cdecl; external 'Soundtracker.dll';   // patternPos brut
  30. function  soundtracker_decoder_get_row(decoder: PStDecoder): Integer; cdecl; external 'Soundtracker.dll';       // row 0-63
  31. function  soundtracker_decoder_get_length(decoder: PStDecoder): Integer; cdecl; external 'Soundtracker.dll';    // nombre d'orders
  32. function  soundtracker_decoder_get_speed(decoder: PStDecoder): Integer; cdecl; external 'Soundtracker.dll';     // vitesse (SPD)
  33. function  soundtracker_decoder_get_bpm(decoder: PStDecoder): Integer; cdecl; external 'Soundtracker.dll';       // BPM
  34. function  soundtracker_decoder_get_cia_mode(decoder: PStDecoder): Integer; cdecl; external 'Soundtracker.dll';  // 1=CIA, 0=vblank
  35. function  soundtracker_decoder_isCompleted(decoder: PStDecoder): Integer; cdecl; external 'Soundtracker.dll';
  36.  
  37. //   module   info
  38. function  soundtracker_decoder_get_version(decoder: PStDecoder): Integer; cdecl; external 'Soundtracker.dll';       // 1=UST, 10=ProTracker...
  39. function  soundtracker_decoder_get_channels(decoder: PStDecoder): Integer; cdecl; external 'Soundtracker.dll';      // nombre de canaux
  40. function  soundtracker_decoder_get_num_patterns(decoder: PStDecoder): Integer; cdecl; external 'Soundtracker.dll';  // nombre de patterns
  41. function  soundtracker_decoder_get_restart(decoder: PStDecoder): Integer; cdecl; external 'Soundtracker.dll';       // position de restart
  42.  
  43. // smpls
  44. function  soundtracker_decoder_get_num_samples(decoder: PStDecoder): Integer; cdecl; external 'Soundtracker.dll';
  45. function  soundtracker_decoder_get_sample_name(decoder: PStDecoder; index: Integer): PAnsiChar; cdecl; external 'Soundtracker.dll';
  46. function  soundtracker_decoder_get_sample_length(decoder: PStDecoder; index: Integer): Integer; cdecl; external 'Soundtracker.dll';
  47. function  soundtracker_decoder_get_sample_volume(decoder: PStDecoder; index: Integer): Integer; cdecl; external 'Soundtracker.dll';
  48. function  soundtracker_decoder_get_sample_finetune(decoder: PStDecoder; index: Integer): Integer; cdecl; external 'Soundtracker.dll';
  49.  
  50. // state voice 0-3
  51. function  soundtracker_decoder_get_channel_note(decoder: PStDecoder; channel: Integer): Integer; cdecl; external 'Soundtracker.dll';
  52. function  soundtracker_decoder_get_channel_period(decoder: PStDecoder; channel: Integer): Integer; cdecl; external 'Soundtracker.dll';
  53. function  soundtracker_decoder_get_channel_sample(decoder: PStDecoder; channel: Integer): Integer; cdecl; external 'Soundtracker.dll';
  54. function  soundtracker_decoder_get_channel_volume(decoder: PStDecoder; channel: Integer): Integer; cdecl; external 'Soundtracker.dll';
  55. function  soundtracker_decoder_is_channel_active(decoder: PStDecoder; channel: Integer): Integer; cdecl; external 'Soundtracker.dll';
  56. function  soundtracker_decoder_get_channel_effect(decoder: PStDecoder; channel: Integer): Integer; cdecl; external 'Soundtracker.dll';
  57. function  soundtracker_decoder_get_channel_param(decoder: PStDecoder; channel: Integer): Integer; cdecl; external 'Soundtracker.dll';
  58. function  soundtracker_decoder_get_channel_finetune(decoder: PStDecoder; channel: Integer): Integer; cdecl; external 'Soundtracker.dll';
  59.  
  60. // set speed
  61. procedure soundtracker_decoder_set_speed(decoder: PStDecoder; speed: Integer); cdecl; external 'Soundtracker.dll';
  62. procedure soundtracker_decoder_set_bpm(decoder: PStDecoder; bpm: Integer); cdecl; external 'Soundtracker.dll';
  63.  
  64. // set channel mute/vol/finetune
  65. procedure soundtracker_decoder_set_channel_volume(decoder: PStDecoder; channel: Integer; vol: Integer); cdecl; external 'Soundtracker.dll';
  66. procedure soundtracker_decoder_set_channel_mute(decoder: PStDecoder; channel: Integer; muted: Integer); cdecl; external 'Soundtracker.dll';
  67. procedure soundtracker_decoder_set_channel_finetune(decoder: PStDecoder; channel: Integer; finetune: Integer); cdecl; external 'Soundtracker.dll';
  68.  
  69. // === Debug !!
  70. procedure soundtracker_decoder_print_data(decoder: PStDecoder); cdecl; external 'Soundtracker.dll';
  71.  
  72. implementation
  73. end.
Coding faster than Light !

hukka

  • Jr. Member
  • **
  • Posts: 57
    • Github
Re: SoundTracker Player Library
« Reply #2 on: February 15, 2026, 01:01:39 am »
I have native crossplatform Free Pascal code for accurate playback of ProTracker/SoundTracker/NoiseTracker, including PowerPacked files, at https://github.com/hukkax/Propulse/tree/trunk/src/protracker

Kind of hidden inside my tracker's sources - I should really make it a separate library like the it2play project for IT modules.

That said, it's cool to have header translations for various libraries, more choices is always good.
« Last Edit: February 15, 2026, 04:06:30 am by hukka »

Gigatron

  • Sr. Member
  • ****
  • Posts: 404
  • Amiga Rulez !!
    • Gigatron Shader Network Demo
Re: SoundTracker Player Library
« Reply #3 on: February 15, 2026, 01:35:38 pm »
Hi
@hukka i know you are a master of pascal code ; It's better using pascal code instead external .dll
sure, but like i said , i'am using this small .dll to share my demos on this forum.

However if you have time it's really interesting to code this player with pascal. (no google translate)

Thanks.
Coding faster than Light !

Gigatron

  • Sr. Member
  • ****
  • Posts: 404
  • Amiga Rulez !!
    • Gigatron Shader Network Demo
Re: SoundTracker Player Library
« Reply #4 on: February 25, 2026, 01:19:09 pm »
I have native crossplatform Free Pascal code for accurate playback of ProTracker/SoundTracker/NoiseTracker, including PowerPacked files, at https://github.com/hukkax/Propulse/tree/trunk/src/protracker

Kind of hidden inside my tracker's sources - I should really make it a separate library like the it2play project for IT modules.

That said, it's cool to have header translations for various libraries, more choices is always good.

I can say the accuracy is perfect with Propulse ! It can play complex module without problems. The soundtracker .dll
can not play modules with many Pt commands,

Must i extract the source from Propules for making Protracker player ?

** Edit ; Started this long project ; Maybe finish this in 2* 13 files := 26 days + 3 days ;
     mean End of March 2026 :)
Impressive Code !!

Regards
« Last Edit: February 25, 2026, 07:44:42 pm by Gigatron »
Coding faster than Light !

Key-Real

  • Sr. Member
  • ****
  • Posts: 404
Re: SoundTracker Player Library
« Reply #5 on: February 25, 2026, 09:53:19 pm »

Gigatron

  • Sr. Member
  • ****
  • Posts: 404
  • Amiga Rulez !!
    • Gigatron Shader Network Demo
Re: SoundTracker Player Library
« Reply #6 on: February 25, 2026, 10:17:16 pm »
Thank you @Key-Real , I will study the code ;
Coding faster than Light !

hukka

  • Jr. Member
  • **
  • Posts: 57
    • Github
Re: SoundTracker Player Library
« Reply #7 on: February 26, 2026, 11:41:13 am »

I can say the accuracy is perfect with Propulse ! It can play complex module without problems. The soundtracker .dll
can not play modules with many Pt commands,

Must i extract the source from Propules for making Protracker player ?

Hi, sorry I missed this earlier. It would be easier for you to use this: https://github.com/hukkax/CaniNES/tree/main/src/basement/playroutines
And look at how the playroutines are used here: https://github.com/hukkax/CaniNES/blob/main/src/basement/basement.audio.pas

Those are part of an old game/demo framework, I'll create a proper PTplay project on github later when I have time to work on it, so as to remove dependencies for BASS/SDL2.

Gigatron

  • Sr. Member
  • ****
  • Posts: 404
  • Amiga Rulez !!
    • Gigatron Shader Network Demo
Re: SoundTracker Player Library
« Reply #8 on: February 26, 2026, 05:39:28 pm »
Thank you @hukka

The conversion code : clean-up SDL2 and BASS are on the way  remain 95%.

Regards
Coding faster than Light !

Gigatron

  • Sr. Member
  • ****
  • Posts: 404
  • Amiga Rulez !!
    • Gigatron Shader Network Demo
Re: SoundTracker Player Library
« Reply #9 on: February 28, 2026, 11:33:05 pm »
It's Partially done :)

Clean-up code remain 45 % , and the result on complex module is nice;

https://www.youtube.com/watch?v=hBGZCYYl3o8

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, OpenGLContext,
  9.   ProTracker.Util, ProTracker.Player, ProTracker_Audio, glCanvas;
  10.  
  11. type
  12.  
  13.   { TForm1 }
  14.  
  15.   TForm1 = class(TForm)
  16.     OpenGLControl1: TOpenGLControl;
  17.     Timer1: TTimer;
  18.     procedure FormCreate(Sender: TObject);
  19.     procedure FormDestroy(Sender: TObject);
  20.     procedure OpenGLControl1Paint(Sender: TObject);
  21.     procedure Timer1Timer(Sender: TObject);
  22.  
  23.   private
  24.   public
  25.   end;
  26.  
  27. var
  28.   Form1: TForm1;
  29.  
  30.   tmr, cltmr : Single;
  31.   txtPosX : Integer;
  32.   demotmr : integer;
  33.   line_message :Array of PChar;
  34.   totalWidth : Single;
  35.   // Textures
  36.   fnt, fnt8, fnt82, fnt32, fntx, tex,laztex : TGLTextureID; //gluint replacement !
  37.   fnt_w,  fnt_h,
  38.   fnt8_w, fnt8_h,
  39.   fnt32_w, fnt32_h,
  40.   tex_w,  tex_h,
  41.   fntx_w, fntx_h : Integer;
  42.   laztex_w,laztex_h : integer;
  43.  
  44. implementation
  45.  
  46. {$R *.lfm}
  47.  
  48. procedure TForm1.FormCreate(Sender: TObject);
  49. begin
  50.  
  51.   glInit(OpenGLControl1);
  52.   glEnableVSync(True);
  53.  
  54.   cltmr :=0; tmr := 0;
  55.   SetLength(line_message, 1);
  56.   line_message[0] := ' *** GIGATRON THE DIGITAL BRAIN PRESENTS -  GLCANVAS PRE RELASE VERSION DEMO 6 - SFX BY : THE GREAT XTD !  SEE YOU BYE *** ';
  57.  
  58.    // Chargement des textures
  59.   fnt   := glLoadPNGToTexture('fonts/chmps30_48.png',      fnt_w,   fnt_h);
  60.   fnt8  := glLoadPNGToTexture('fonts/16/021_16.png',       fnt8_w,  fnt8_h);
  61.   fnt32 := glLoadPNGToTexture('fonts/32/razor1911_32.png', fnt32_w, fnt32_h);
  62.   fntx  := glLoadPNGToTexture('fonts/32/022_32.png',       fntx_w,  fntx_h);
  63.   tex   := glLoadJPGToTexture('gfx/aa512x512.jpg',         tex_w,   tex_h);
  64.   laztex := glLoadPNGToTexture('gfx/gtr5.png',             laztex_w,  laztex_h);
  65.   // module
  66.   Module := TPTModule.Create(True, False);
  67.   Module.Stop;
  68.   Module.LoadFromFile('modules/## syntherella 3 ##.mod');
  69.   PT_Audio_SetPaused(False);
  70.   Module.SetAmplification(0.6);
  71.   Module.SetStereoSeparation(50);
  72.  
  73.   PT_Audio_Init;
  74.   Module.Play(0, 0);
  75. end;
  76.  
  77. procedure TForm1.OpenGLControl1Paint(Sender: TObject);
  78. var
  79.   i, ww,hh : integer;
  80.     scaleVal : Single;
  81.   posX : Integer;
  82.   accumX : Single;
  83. begin
  84.    ww := OpenGLControl1.Width;
  85.    hh := OpenGLControl1.Height;
  86.    glFillScreen(OpenGLControl1, 0.0, 0.0, 0.0, 1.0);
  87.  
  88.  
  89.   if(demotmr>1500) then
  90.   glCheckerBoard(0,0,ww,hh,sin(tmr*0.3)*2.0,cos(-tmr*0.2)*3.0,
  91.                  sin(cltmr *0.1),cos(cltmr*0.15),sin(cltmr*0.20))
  92.   else
  93.   glCheckerBoard(0,0,ww,hh,sin(tmr*0.2)*4.0,cos(-tmr*0.1)*2.0,
  94.                  1.0,0.0,0.0);
  95.  
  96.     glTextureCopperShader(laztex,440,0,laztex_w ,laztex_h ,tmr*0.02,64.0,
  97.      0.95,1.0,0,
  98.      0.0, 0.0, 1.0,
  99.      1.0, 1.0, 1.0,
  100.      0.5 + abs(sin(tmr*0.1)) * 0.5,
  101.      0.5 + abs(sin(tmr*0.2)) * 0.5,
  102.      0.5 + abs(cos(tmr*0.1)) * 0.5,
  103.      0.0, 0.0, 1.0,1.0,
  104.      1.0,1.0,1.0);
  105.  
  106.  
  107.      accumX := 0;
  108.     for i := 0 to Length(line_message[0])-1 do
  109.       begin
  110.         scaleVal := 5.0 + sin(tmr*0.2 + i * 0.3) * 2.0;
  111.         glBitmapFontText(fntx, Round(3200 + accumX) - txtPosX, 400, line_message[0][i],
  112.                          32, 32, 10, 1.0, 0.0, bmAlpha,
  113.                          scaleVal,
  114.                          5.0 + cos(tmr*0.2 + i * 0.3) * 2.0);
  115.         accumX := accumX + (32 * scaleVal) + 10;
  116.     end;
  117.      totalWidth := accumX;
  118.  
  119.  
  120.    glFilled3DCube(OpenGLControl1,0,30,0,50,0.4,0.4,0.4,1.0,
  121.                                   tmr*6,tmr*8,0.0,1.0,0.0,1.0,
  122.                                   true,0.5 + abs(sin(tmr*0.3)) * 0.5,
  123.                                        0.5 + abs(sin(tmr*0.2)) * 0.5,
  124.                                        0.5 + abs(cos(tmr*0.1)) * 0.5,
  125.                                        4.0);
  126.  
  127.    glScreenReflectShader(OpenGLControl1,0.4,0.004,50.0,tmr*0.2, 10.0);
  128.  
  129.    OpenGLControl1.SwapBuffers;
  130. end;
  131.  
  132. procedure TForm1.Timer1Timer(Sender: TObject);
  133. begin
  134.   inc(demotmr);
  135.   if (demotmr>200) then  tmr := tmr + 0.2;
  136.  
  137.   cltmr := cltmr + 0.1;
  138.  
  139.   txtPosX := txtPosX + 5;
  140.   if txtPosX > Round(3200 + totalWidth) then txtPosX := 0;
  141.  
  142.   OpenGLControl1.Invalidate;
  143. end;
  144.  
  145. procedure TForm1.FormDestroy(Sender: TObject);
  146. begin
  147.   if Module <> nil then Module.Stop;
  148.   PT_Audio_Close;
  149.   if Assigned(Module) then FreeAndNil(Module);
  150. end;
  151.  
  152. end.
Coding faster than Light !

hukka

  • Jr. Member
  • **
  • Posts: 57
    • Github
Re: SoundTracker Player Library
« Reply #10 on: March 01, 2026, 02:18:37 am »
It's Partially done :)

Clean-up code remain 45 % , and the result on complex module is nice;

Cool! Nice scroller. Have you considered making some Amiga prods? 68000 assembler is fun :)

Gigatron

  • Sr. Member
  • ****
  • Posts: 404
  • Amiga Rulez !!
    • Gigatron Shader Network Demo
Re: SoundTracker Player Library
« Reply #11 on: March 01, 2026, 09:29:18 pm »
It's Partially done :)

Clean-up code remain 45 % , and the result on complex module is nice;

Cool! Nice scroller. Have you considered making some Amiga prods? 68000 assembler is fun :)

Ah, maybe after Lazarus FPC , i remember 68000 ; and some mnemonics ; moveq, move.b w l  , lea bsr bra dfb $dffxxx etc ... :) 30 days for learn again ...
Coding faster than Light !

 

TinyPortal © 2005-2018