PDA

View Full Version : JEDI-SDL Audio



DarknessX
28-05-2007, 12:37 AM
Hey, well, I just setup Free Pascal (pure, not lazarus, etc) to work with Jedi-SDL. It's working fine, compiles, can initiate and exit Jedi-SDL's audio using:


Program testsdl;

uses sdl;

begin
sdl_init(SDL_INIT_AUDIO);

sdl_quit;
end.


But I don't know how to load an audio file, then play/pause/stop it. Any help? Some example code, without using graphical windows? I'm going to be doing all my code via text-based, so all the 'forms' and such don't help me :(

Also, I can't find the demo programs... I'm using the v1 beta, and I've looked (AFAIK) everywhere.

paul_nicholls
28-05-2007, 02:21 AM
Go to here http://jedi-sdl.cvs.sourceforge.net/jedi-sdl/JEDI-SDLv1.0/SDL_Mixer/Demos/WavTest/

and you will find a SDL_Mixer demo...is this what you were looking for?

cheers,
Paul.

savage
28-05-2007, 09:38 AM
You may also want to check out this thread (http://www.pascalgamedevelopment.com/viewtopic.php?p=34556)

which discusses an sdl_mixer audio manager class I wrote a while a go.

DarknessX
28-05-2007, 10:48 AM
I believe thats what I was looking for, paul_nicholls. But I need it to play mp3's too :P

jasonf
28-05-2007, 11:07 AM
SDL Mixer plays MP3 and OGG Vorbis among others, you just need to make sure you have the correct dlls and units referenced. smpeg I think.

The JEDI-SDL examples in the JEDI-SDL folder will help a lot.

I got a lot of info for using SDL from the book Programming Linux Games by NoStarch press..http://www.nostarch.com/frameset.php?startat=plg

But there's nothing in there you can't glean from the SDL documentation on the libSDL site. http://www.libsdl.org/cgi/docwiki.cgi/SDL_5fmixer

OK, so it's all in C but it's easy to read.

WILL
28-05-2007, 02:26 PM
Sorry, I know this is only slightly relevant, but because it was brought up. Even the C examples for things like SDL, OpenGL, etc are super useful because the function names are the same and the values that you pump into them are the same.

The SDL Audio mixer is pretty decent for cross platform. I don't know of any other way to get the same kind of audio on all 3 major OSes, except for OpenAL. (which isn't too bad/hard either tbh)

One thing to note however the SDL_Mixer does not playback at 44100 Hz on Windows very well. For whatever reason. :scratch: On Linux it's perfectly fine, but for Windows it just gives you a really distorted output. You best bet for Win32/64 would be to playback at 22050 Hz instead.

Oh and before I forget, do look for the included documentation with the latest release. It should have full listing of all the functions you'd need.

DarknessX
28-05-2007, 07:02 PM
I couldn't find the examples in the Jedi-SDL folder... I looked. Nothing there :(

I don't know C, and can't understand enough to be able to figure out the values.

WILL
28-05-2007, 08:13 PM
I've recently done a major reconstruction of the new JEDI-SDL site. You can find online documentation there.

EDIT: Sorry forgot to post the link in case you don't know it: jedi-sdl.pascalgamedevelopment.com (http://jedi-sdl.pascalgamedevelopment.com/)

DarknessX
28-05-2007, 10:36 PM
Well, I'm overly confused. I have no clue how to initialize and play audio. I've been going through examples, code, tutorials, everything I can find, and I'm lost :(

WILL
29-05-2007, 01:11 AM
You're looking for a Demo in the JEDI-SDL 1.0 BETA release. it's located under the path JEDI-SDLv1.0\SDL_Mixer\Demos\WavTest There, albeit sort of hidden.

Psst... Dom, you you need someone to make FPC/Lazarus demos for ya? These are kind of useless to a non-Delphi guy. :P


--- Please note that this demo is not very straightforward and could probably be vastly improved. ---


Since you are not using Delphi (or Kylix) you will not be able to just run and test it. So open up the Main.pas file and you'll see all the code you'll need.

Considering that this code is pretty poor to make reference to I'll just cut out all the junk and post what you'll need from it. But don't let that stop you from actually going to check out the demo it's self!

Don't forget to add the DLLs to the game folder!

uses
sdl,
sdl_mixer;

// initialization
var
audio_rate: integer;
audio_format: Uint16;
audio_channels: integer;
audio_buffers : integer;
loops: integer;

loops := 0;
if ((SDL_Init(SDL_INIT_AUDIO) < 0)) then
begin
// Could not initialize SDL Audio
SDL_Quit;
exit;
end
else
begin
audio_rate := StrToInt(seAudioRate.Text);
audio_format := StrToInt(seAudioFormat.Text);
audio_channels := StrToInt(seAudioChannels.Text);
audio_buffers := StrToInt(seAudioBuffers.Text);
// Open the audio device
if ( Mix_OpenAudio( audio_rate, audio_format, audio_channels, audio_buffers ) <0> 1) then
// Memo.Lines.Add(Format('Opened audio at %d Hz %d bit %s', [audio_rate, (audio_format and $FF), 'stereo']))
else
// Memo.Lines.Add(Format('Opened audio at %d Hz %d bit %s', [audio_rate, (audio_format and $FF), 'mono']));


// Load the requested wave file * /
wave := Mix_LoadWAV(PChar(Edit1.Text)); // Edit1.Text is the WAV file path string
if (wave = nil) then
exit;

// Play and then exit * /
Mix_PlayChannel(0, wave, loops);
while ( Mix_Playing(0) = 0 ) do
SDL_Delay(100);
end;

// now we closing everything

if ( wave <> nil ) then
begin
Mix_FreeChunk(wave);
wave := nil;
end;
if ( bAudioOpen ) then // bAudioOpen is just some flag that was used to keep track if the audio device was opened.
begin
Mix_CloseAudio;
end;
SDL_Quit;

// Done!

If you want more in depth information about all the other functions: Read (http://jedi-sdl.pascalgamedevelopment.com/docs.php?page=audio.html#Docs) :)

DarknessX
29-05-2007, 08:06 PM
That all works, except one thing. It won't load my audio files. I'm using this code:


//{$mode delphi}
Program testsdl;

uses sdl, sdl_mixer, sysutils;

var
audio_rate: integer;
audio_format: Uint16;
audio_channels: integer;
audio_buffers : integer;
loops: integer;
wav : word;
wave : pmix_chunk;
baudioopen : boolean;

begin
loops := 0;
SDL_INIT(SDL_INIT_AUDIO);
if ((SDL_INIT(SDL_INIT_AUDIO) < 0)) then begin
Sdl_Quit;
exit;
end
else
begin
writeln('1');
audio_rate := 22050;
audio_format := wav;
audio_channels := 2;
audio_buffers := 4064;
baudioopen := false;
writeln('2');
wave := mix_loadwav('wakeup.wav');
if wave = nil then exit;
mix_playchannel(0, wave, loops);
while (mix_playing(0) = 0 ) do sdl_delay(100);
writeln('3');
end;
if wave <> nil then begin
writeln('free');
mix_freechunk(wave);
wave := nil;
end;
if ( bAudioOpen ) then // bAudioOpen is just some flag that was used to keep track if the audio device was opened.
begin
Mix_CloseAudio;
writeln('4');
end;
readln;
SDL_Quit;
end.


If I run it in a command prompt, it shows me up to '2' and then closes... Right where if wave = nil. If I comment that out, it gives me an error- basically, can't play 'nil'.

savage
29-05-2007, 08:59 PM
So where is your wav file located?

DarknessX
29-05-2007, 09:13 PM
In the same folder as the app. Originally it was in C:\sounds\wakeup.wav, and the path was appropriate, but I though that MAYBE for some reason it couldn't handle a full path and so switched it to the same directory. The EXE, and the .wav, is in C:\projects\tests\jedisdl\

savage
29-05-2007, 09:16 PM
What type of Wav file is it? Is it using some kind of funky compression?

DarknessX
29-05-2007, 09:17 PM
No its not using any... I made it myself. I also tried an MP3 file (it does support mp3's, according to the jedi-sdl site) but that didn't work either.

savage
29-05-2007, 09:20 PM
Have you tried Mix_GetError after the call to mix_loadwav? What does it say? If not, why not?

DarknessX
29-05-2007, 09:21 PM
Didn't realize I could :P I'll try it right now :)

OK, Audio Device hasn't been opened.

savage
29-05-2007, 09:37 PM
So what does that tell you? What have you missed?

DarknessX
29-05-2007, 10:21 PM
No clue, cause I don't know how to initialize the audio :(

savage
29-05-2007, 10:28 PM
WILL posted an example earlier. Look for Mix_OpenAudio in this thread.

If someone posts an example, please make sure that what you have tried is not already mentioned.

DarknessX
29-05-2007, 10:30 PM
The open_audio doesn't work with his method though... Open audio uses obtained.blah and and desired.blah which does not work in non-oop, while I was under the impression his example was non-oop.

EDIT: nevermind. I was thinking sdl_openaudio :P Now it works, sort of.

And, .mp3 files don't work :( The original SDL supported MP3's too... Is there anything specific I need to change to make it work with MP3's?

savage
29-05-2007, 10:38 PM
It supports MP3s through smpeg.dll and only certain MP3 types. Which types exactly I have not worked out yet as I have not had the need.

DarknessX
29-05-2007, 10:40 PM
Well, I have smpeg.dll in there (obviously, or else it wouldn't work :P) and I tried taking a plain music file, didn't work. I tried using another music file, again, didn't work. They don't have protection on them. Is it possible for me to 'add' support for them, hopefully easily?

paul_nicholls
29-05-2007, 10:53 PM
The open_audio doesn't work with his method though... Open audio uses obtained.blah and and desired.blah which does not work in non-oop, while I was under the impression his example was non-oop.

EDIT: nevermind. I was thinking sdl_openaudio :P Now it works, sort of.

And, .mp3 files don't work :( The original SDL supported MP3's too... Is there anything specific I need to change to make it work with MP3's?

it only supports mp3 (and ogg format) if you use smpeg and Mixer_LoadMUS(), etc. instead of Mixer_LoadWAV().

like this:


Var
bAudioOpen &#58; Boolean;
music &#58; PMix_Music;

Initialization

bAudioOpen &#58;= False;
Log&#40;'Initializing...'&#41;;
If SDL_Init&#40;SDL_INIT_AUDIO Or SDL_INIT_VIDEO Or SDL_INIT_JOYSTICK&#41; < 0 Then
Begin
Log&#40;'Could not initialize SDL'&#41;;
Exit;
End


I open the audio

audio_rate &#58;= 22050;//MIX_DEFAULT_FREQUENCY;
audio_format &#58;= AUDIO_S16SYS;
audio_channels &#58;= MIX_DEFAULT_CHANNELS;
audio_buffers &#58;= 4096;
// Open the audio device
Log&#40;'Opening audio...'&#41;;
If Mix_OpenAudio&#40;audio_rate, audio_format, audio_channels, audio_buffers&#41; < 0 Then
Begin
Log&#40;Format&#40;'Could not open audio&#58; %s', &#91;SDL_GetError&#93;&#41;&#41;;
Exit;
End


I then play the music if that went ok:

Procedure PlayMusic&#40;AFileName&#58; AnsiString; loops&#58; Integer&#41;;
Begin
Log&#40;'Loading music...'&#41;;
music &#58;= Mix_LoadMUS&#40;PChar&#40;AFileName&#41;&#41;;
If &#40;music = Nil&#41; Then
Begin
Log&#40;Format&#40;'Could not load "%s"&#58; %s', &#91;AFileName, SDL_GetError&#40;&#41;&#93;&#41;&#41;;
Exit;
End;
Log&#40;'Music loaded'&#41;;
If loops <> -1 Then
Begin
Log&#40;Format&#40;'Playing&#58; "%s"&#40; looping &#41;',&#91;AFileName&#93;&#41;&#41;;
End
Else
Log&#40;Format&#40;'Playing&#58; "%s"&#40; not looping &#41; ',&#91;AFileName&#93;&#41;&#41;;
Mix_PlayMusic&#40;music, loops&#41;;
Log&#40;'Playing'&#41;;
End;

After everything is finished I cleanup

Procedure Cleanup;
Begin
If music <> Nil Then
Begin
Log&#40;'Freeing music...'&#41;;
Mix_FreeMusic&#40;music&#41;;
Log&#40;'Music freed'&#41;;
music &#58;= Nil;
End;
If bAudioOpen Then
Begin
bAudioOpen &#58;= False;
Log&#40;'Closing audio...'&#41;;
Mix_CloseAudio;
Log&#40;'Audio closed'&#41;;
End;
SDL_Quit;
End;


My complete example program (ignore gp2x bits) that works on windows.


Program gp2x_sdl_mixer;
&#123;$IFDEF fpc&#125;
&#123;$MODE Delphi&#125; &#123;$H+&#125;
&#123;$ENDIF&#125;

Uses
sdl_mixer,
sdl,
SysUtils;

Var
bAudioOpen &#58; Boolean;
music &#58; PMix_Music;
screen &#58; PSDL_Surface;

&#123;................................................. .............................&#125;

&#123;................................................. .............................&#125;
Procedure Log&#40;AString&#58; AnsiString&#41;;
Var
FileName &#58; AnsiString;
LogFile &#58; Text;
Begin
FileName &#58;= ExtractFilePath&#40;ParamStr&#40;0&#41;&#41; + 'LogFile.txt';
AssignFile&#40;LogFile,FileName&#41;;
If FileExists&#40;FileName&#41; Then
Append&#40;LogFile&#41;
Else
Rewrite&#40;LogFile&#41;;
WriteLn&#40;LogFile,AString&#41;;
Flush&#40;LogFile&#41;;
CloseFile&#40;LogFile&#41;;
End;
&#123;................................................. .............................&#125;

&#123;................................................. .............................&#125;
Function Initialize&#58; Boolean;
Var
audio_rate &#58; integer;
audio_format &#58; Uint16;
audio_channels &#58; integer;
audio_buffers &#58; integer;
Begin
Result &#58;= False;
bAudioOpen &#58;= False;
Log&#40;'Initializing...'&#41;;
If SDL_Init&#40;SDL_INIT_AUDIO Or SDL_INIT_VIDEO Or SDL_INIT_JOYSTICK&#41; < 0 Then
Begin
Log&#40;'Could not initialize SDL'&#41;;
Exit;
End
Else
Begin
screen &#58;= SDL_SetVideoMode&#40;320,240,16,SDL_SWSURFACE&#41;;
If screen = Nil Then
Begin
Log&#40;Format&#40;'Could not create window&#58; %s',&#91;SDL_GetError&#93;&#41;&#41;;
Exit;
End;
Log&#40;'Window created'&#41;;
SDL_ShowCursor&#40;0&#41;;
audio_rate &#58;= 22050;//MIX_DEFAULT_FREQUENCY;
audio_format &#58;= AUDIO_S16SYS;
audio_channels &#58;= MIX_DEFAULT_CHANNELS;
&#123;$IFDEF gp2x&#125;
audio_buffers &#58;= 512;
&#123;$ELSE&#125;
audio_buffers &#58;= 4096;
&#123;$ENDIF&#125;
// Open the audio device
Log&#40;'Opening audio...'&#41;;
If Mix_OpenAudio&#40;audio_rate, audio_format, audio_channels, audio_buffers&#41; <0> 1&#41; Then
Log&#40;Format&#40;'Opened audio at %d Hz %d bit %s', &#91;audio_rate,
&#40;audio_format and $FF&#41;, 'stereo'&#93;&#41;&#41;
Else
Log&#40;Format&#40;'Opened audio at %d Hz %d bit %s', &#91;audio_rate,
&#40;audio_format and $FF&#41;, 'mono'&#93;&#41;&#41;;
End;
End;
Result &#58;= True;
bAudioOpen &#58;= True;
Log&#40;'Initialized'&#41;;
End;
&#123;................................................. .............................&#125;

&#123;................................................. .............................&#125;
Procedure PlayMusic&#40;AFileName&#58; AnsiString; loops&#58; Integer&#41;;
Begin
Log&#40;'Loading music...'&#41;;
music &#58;= Mix_LoadMUS&#40;PChar&#40;AFileName&#41;&#41;;
If &#40;music = Nil&#41; Then
Begin
Log&#40;Format&#40;'Could not load "%s"&#58; %s', &#91;AFileName, SDL_GetError&#40;&#41;&#93;&#41;&#41;;
Exit;
End;
Log&#40;'Music loaded'&#41;;
If loops <> -1 Then
Begin
Log&#40;Format&#40;'Playing&#58; "%s"&#40; looping &#41;',&#91;AFileName&#93;&#41;&#41;;
End
Else
Log&#40;Format&#40;'Playing&#58; "%s"&#40; not looping &#41; ',&#91;AFileName&#93;&#41;&#41;;
Mix_PlayMusic&#40;music, loops&#41;;
Log&#40;'Playing'&#41;;
End;
&#123;................................................. .............................&#125;

&#123;................................................. .............................&#125;
Procedure Cleanup;
Begin
If music <> Nil Then
Begin
Log&#40;'Freeing music...'&#41;;
Mix_FreeMusic&#40;music&#41;;
Log&#40;'Music freed'&#41;;
music &#58;= Nil;
End;
If bAudioOpen Then
Begin
bAudioOpen &#58;= False;
Log&#40;'Closing audio...'&#41;;
Mix_CloseAudio;
Log&#40;'Audio closed'&#41;;
End;
&#123;$IFNDEF gp2x&#125;
SDL_Quit;
&#123;$ELSE&#125;
chdir &#40;'/usr/gp2x'&#41;;
ExecuteProcess&#40;'/usr/gp2x/gp2xmenu',&#91;'/usr/gp2x/gp2xmenu'&#93;&#41;;
&#123;$ENDIF&#125;
End;
&#123;................................................. .............................&#125;

&#123;................................................. .............................&#125;
Procedure WaitForKeyUp&#40;AKey&#58; Uint32&#41;;
Var
event &#58; TSDL_Event;
done &#58; Boolean;
Begin
done &#58;= False;

While Not done Do
Begin
SDL_Delay&#40;1&#41;;
While SDL_PollEvent&#40;@event&#41; = 1 Do
Begin
If event.type_ = SDL_KEYUP Then
If event.key.keysym.sym = AKey Then done &#58;= True;
End;
End;
End;
&#123;................................................. .............................&#125;

&#123;................................................. .............................&#125;
Procedure WaitForJoystickButtonUp&#40;AButton&#58; Uint32&#41;;
Var
event &#58; TSDL_Event;
done &#58; Boolean;
Begin
done &#58;= False;

While Not done Do
Begin
SDL_Delay&#40;1&#41;;
While SDL_PollEvent&#40;@event&#41; = 1 Do
Begin
If event.type_ = SDL_JOYBUTTONUP Then
If event.jbutton.button = AButton Then done &#58;= True;
End;
End;
End;
&#123;................................................. .............................&#125;

&#123;................................................. .............................&#125;
Begin
Try
DeleteFile&#40;ExtractFilePath&#40;ParamStr&#40;0&#41;&#41; + 'LogFile.txt'&#41;;
If Initialize Then
Begin
PlayMusic&#40;ExtractFilePath&#40;ParamStr&#40;0&#41;&#41; + 'Pet Shop Boys - 02 - West End Girls.mp3',0&#41;;
&#123;$IFNDEF gp2x&#125;
WaitForKeyUp&#40;SDLK_Escape&#41;;
&#123;$ELSE&#125;
WaitForJoystickButtonUp&#40;SDLK_GP2X_START&#41;;
&#123;$ENDIF&#125;
End
Else
Log&#40;'Initializing failed.'&#41;;
Except
On E&#58;Exception Do Log&#40;E.Message&#41;;
End;
Log&#40;'closing...'&#41;;
Cleanup;
End.

I hope this helps
cheers,
Paul.

savage
30-05-2007, 12:09 AM
Thanks Paul, I totally forgot to mention that you need to use Mixer_LoadMUS and not Mixer_LoadWav for other music formats.

WILL
30-05-2007, 12:26 AM
Mixer_LoadMUS can also load MOD, S3M, XM and IT modules as well. If you know what a tracker is then you'll know all about these.

DarknessX
30-05-2007, 01:56 AM
begin
SDL_INIT(SDL_INIT_AUDIO);
if baudioopen = true then begin
writeln('Error! SDL Audio could not be initialized.');
sdl_quit;
readln;
exit;
end
else
begin
writeln('stage 1- initialization');
baudioopen := false;
audio_rate := 22050;
audio_format := AUDIO_S16SYS;
audio_channels := MIX_DEFAULT_CHANNELS;
song := 'testx.mp3';
//song := 'test.wav';
wave := mix_loadmus(song);
error := mix_geterror;
writeln(error);
if wave = nil then begin
writeln('Couldn''t load ',song,'.');
sdl_quit;
readln;
exit;
end;
mix_playmusic(wave,loops);
if wave <> nil then begin
mix_freemusic(wave);
wave := nil;
end;
if baudioopen then begin
baudioopen := false;
mix_closeAudio;
end;
sdl_quit;
end;
end.


Ok, thats my code. The result, depending on the audio file being run, is:
WAV File:

Couldn't Load WAV File.


MP3 File:

Module Format not Recognized.


Anyone have a clue where my problem is?

paul_nicholls
30-05-2007, 03:23 AM
You could try downloading the zip file from here (http://www.pygame.org/ftp/win32-dependencies.zip).

This contains a smpeg.dll that you could use instead of whatever you are currently using...I had problems till I used that one.

cheers,
Paul.

savage
30-05-2007, 07:09 AM
DarkNess, in the code you posted where is the call to Mix_OpenAudio?

Also you are using mix_playmusic to play WAV files. I don't think that will work.

DarknessX
30-05-2007, 08:03 PM
begin
SDL_INIT(SDL_INIT_AUDIO);
if baudioopen = true then begin
writeln('Error! SDL Audio could not be initialized.');
sdl_quit;
readln;
exit;
end
else
begin
writeln('stage 1- initialization');
writeln(mix_geterror);
readln;
baudioopen := false;
audio_rate := 22050;
audio_format := AUDIO_S16SYS;
audio_channels := MIX_DEFAULT_CHANNELS;
audio_buffers := 4096;
mix_openaudio(audio_rate,audio_format,audio_channe ls, audio_buffers);
writeln('stage 2- set song file');
song := 'testb.mp3';
wave := mix_loadmus('testb.mp3' {normally var song} );
error := mix_geterror;
writeln(error);
if wave = nil then begin
writeln('Couldn''t load ',song,'.');
sdl_quit;
readln;
exit;
end;
writeln('stage 3- play song');
writeln(mix_geterror);
repeat
loops := 1;
mix_playmusic(wave,loops);
until bool = true;
if wave <> nil then begin
mix_freemusic(wave);
wave := nil;
end;
if baudioopen then begin
baudioopen := false;
mix_closeAudio;
end;
writeln('stage 4- quit');
sdl_quit;
end;
end.


Ok. This is my new code. My problem being, instead of playing the file, I hear a bunch of ticks. It's running testb.mp3, and it works, except instead of the song, I hear ticks. Now, if I try .wav, I get an error stating:
"You can't pass a FILE pointer to a DLL (?)"
with that exact caps, including the (?). I have no clue what this means.