OAL/DS MaxMod Beta Test

BlitzMax Forums/BlitzMax Programming/OAL/DS MaxMod Beta Test

I've been working on the next version of maxmod that uses both DirectSound and OpenAL depending on which audio driver blitzmax is using at the time...

http://code.google.com/p/maxmod/

unfortunately I'm unable to test this on mac,linux,vista or 64bit, if anybody has a spare few minutes to test it for me I would be very grateful. (I'm expecting problems with endianness (is that right?) ect)

The new version provides a TSampleLoader for the standard loadsound command, and a seperate streaming module. I've also completly changed the command set to be more blitzmax friendly, just call the new CreateAudioStream command and it will return a TChannel for use with the built-in channel commands. (see the documention for examples ect)

Please note that you must change the audio driver to either "OpenAL" or "DirectSound" for streaming to work, the default "FreeAudio" driver will not produce any sound.

one problem at the moment is that I swapped it to using the Pub.DirectX module for directsound support, which has added a bug that should be fixed with the release of blitzmax 1.28, but until then any testers may need to correct line 140 in "pub/directx.mod/dsound.bmx" from this...
Method GetCurrentPosition( pos Var )
to this...
Method GetCurrentPosition(playpos Var, writepos Var)


Please delete any previous version of maxmod first, then extract the archive to your "blitzmax/mod" folder, that will create a "maxmod.mod" folder which contains "modplayer.mod" and "audiostream.mod"

Thanks in advance.

Thinking about it, are the docs still unreadable on linux?

if they are you may need to load the examples manualy, you'll find them in the docs folders of audiostream.mod and modplayer.mod
obviously you'll also need to change the audio driver in the examples to openal.

I'm expecting problems with endianness

You may only experience this on PPC based Macs. Everything else should be fine. Can't test your mod at the moment though, as I'm at work.

Cue the tumble weed. LOL.

No worries, public release of this is now dropped, I dont even use this (as is) myself, other than to support mod files in my DJ/Tracker app, which uses a completely different mixer anyway.

No point wasting precious time flogging a dead horse.

Thanks anyway, LOL. :)

You do realize that any replies you had within the past two days have been wiped by the server change, right? I'm not saying I know there were more replies, or how many, just making sure you knew that any replies would be gone.

http://66.103.20.15/Community/posts.php?topic=74048 ;)

Dont get me wrong, I'm not thowing my toys out the pram!
Just being realistic, If people wanted crossplatform streaming, they would make a effort. if not, neither will I.

(DOH, that still sounds like a tantrum LOL, but i'm sure you get my point)

I'm just thinking that a time when the DNS changes have made the site inaccessible for long periods and where the forums have "split" might not be the best time to judge a response.

But hey, I don't know the history. Maybe there was limited interest in previous releases.

REDi, your hard work will not be in vain: To me, ALL BMax modules should try as hard as yours does to be cross-platform. I wish I could test it for you, but alas, I only have a WinBox...

If there's an Amiga port to be tested, I have 3 in the closet waiting to be used! (I'm not kidding!)

But seriously, can someone with a Mac or Linux machine test this for REDI?

Russell

I see your point Gabe, just incase I'll leave it up for a tad longer.

But honestly guys, I'd like to hear you true opinions on this. (kill it or not)

*EDIT* Thanks Russell ;)

Hi REDi, I get your point although another post suggested NOT using Maxmod until 1.28 was released. I assumed this post was just for feedback on mac, linux, vista and 64bit but if you want win32 feedback I'm happy to try it.
I am sufgfering from a general malaise with Bmax at the moment. BRL seem uncommitted and less communicative than normal : which is difficult. I appreciate the effort you and other coders are putting in to improve the product but it *does* seem like a waste of time sometimes. My attempt to plug some gaps fell on deaf ears with just a few suggestions which then received no feedback. Personally, I'd like to see some of the third party improvements upgraded to the full product as, one-by-one, they seem to become incompatible as the releases change. Anyway, thanks for what you have done so far.

Thanks Tony, has it got that bad lately? I havent been about for quite a while (moved house, spent time in hospital ect), so i dont really know whats going on atm, does seem to be less activity than before.

Shame because I do enjoy blitzmax as a language.

Redi,

Some testing results on Vista:

SampleMusic Test - Plays fine, but there is the occasional pause when you do other things on the PC.

Stream Test - Plays fine! no pausing etc.

Ogg Export - Worked fine and the resultant file played no probs.

Max GUI - Can't sync that at the moment.

? Sorry Matt, is that the beta download from http://code.google.com/p/maxmod/

SampleMusic ect doesnt exist anymore, you just Import MaxMod.ModPlayer and use LoadSound:TSound

Think ya got the wrong one mate ;)

REDi, I have an Intel Mac, and Ubuntu 7.10 running on a PC, and am happy to test.

The Mac is running Leopard, and I believe there may be issues that need 1.28, but I will check it out. possibly not until tomorrow though

Cheers.

Rog.

Thanks Roger, much appreciated mate!

Redi,

Yep thats the one. Ahh.. actually, I just unzipped it over the top... I'll take another look.

Does work though!

just tryed to compile in my OSX 10.4.11 (mac Intel)
and Max Says.. "Can't find interface for module "maxmod.music"

decompressesd under my mod folder...

XP SP2 and tested, works very well.

A side note, most of us can't even see the mysterious BlitzMax 1.28 release currently so can't make a comment yet.

I can only say MaxMod is VERY nice and I hope it can be continously maintained, OGG stream will be a plus as most of us don't know how to do it, but BRL must fix their audio driver first I think.

Thanks a lot for your help and kind words guys, it is appreciated! maybe it'll live to see another day :)

GregBug, thanks mate, I get the same error if I delete all the win32 compiled files and do a rebuild. Will fix ASAP. (would have thought max would have caught that and compiled maxmod.music first, anyone else think this is a bug?)


most of us can't even see the mysterious BlitzMax 1.28 release


yeah, neither can I :)

ok, new version up that should fix the build modules problem. I ended up just renaming it to maxmod.amusic and it compiles them in the correct order. hope it works like that on all platforms.

Anyone able to test on Linux yet?

Russell

Hio,

i don't know what the expected behaviour here is but is it supposed to stay still for ~10-15 seconds at 100% CPU before starting to play music?

If not I bet it has to do with me using the crappy onboard soundchip.

That test was on WinXP SP2

Redi: I haven't tried the latest release yet, but anyway: MaxMod is definitely a very useful mod, and much appreciated.

Hi North, was that using the LoadSound method, or streaming with CreateAudioStream?

The LoadSound way will take various amounts of time to produce the entire song in one go, like loading an ogg file. some mods/xms are very long, even up to 10mins+! so creating ~100mb+ of audio can take a long time. you could watch task manager to see how big the sound gets.

also the more channels in the song the longer it'll take to create, Loading the entire song in one go is really only useful for reasonably small mods/xms.

but if your streaming and getting that amount of pause, please send me a copy of the file if possible, and I'll see whats going on.

*EDIT* Thanks xlsior, I think *maybe* I was over estimating the number of mac/linux users on here?, dont know really, guess I was over reacting.

Ouch! Just downloaded the new version from google codes, and winrar came up with a cached version from 4 days ago!!!

Please right click and "save target as" if you've downloaded a previous version before just incase.

Think I'm gonna have to change the file name each release?

Hi REDi,

this was with LoadSound - so i understand this works as expected.

I will try the Streaming soon.

Thanks for such a nice mod - i love the old tracks ;)

Phew, ya had me worried North ;)
Thanks for testing it mate, fingers crossed the streaming works for ya.

HI REDI,
just redownloaded and when i try to compile

max says: "Idetifier IDirectSound not found" in file directsoundaudiostream.bmx

....some win32 include file ins OSX? (directsound....)

my system OSX 10.4.11 BMax 1.26

ciao.

with compiler directive i have not included DirectSound referece and now compile without error...

any ready source sample to test you module ?(i must back to work and no time to write some test code...now)

gianluca.

There is an example in mod/maxmod.mod/audiostream.mod/doc
-----

Trying to compile the mod (or rebuilding all mods) gives the following error on linux:


Compiling:audiostream.bmx
ar: creating /BlitzMax/mod/brl.mod/blitz.mod/blitz.debug.linux.x86.a
Compile Error: Can't find interface for module 'maxmod.amusic'
[/BlitzMax/mod/maxmod.mod/audiostream.mod/audiostream.bmx;22;1]
Build Error: failed to compile /BlitzMax/mod/maxmod.mod/audiostream.mod/audiostream.bmx
Process complete



after first compiling maxmod.amusic via comandline and changing lines 18, 23 and 72 in audiostream.bmx (the lines containing DirectSound references) the whole thing does compile on linux (open SuSE 10.3) and seems to work ok with freeaudio.
However loading xm/mod-files takes very long ( around 3 seconds for less then 2kb, more then 20 seconds for 926kb)


Streaming OGGs using the example-source does result in too fast played music with additional noise.

I just tested streaming and its working very nicely.

One thing struck me odd - check this piece:

Import MaxMod.AudioStream
Import MaxMod.ModPlayer

'EnableOpenALAudio()
'SetAudioDriver("openal")
SetAudioDriver("directsound")

Local file$ = RequestFile( "", MusicExtensions() )
Graphics 320,40,0 ; Cls ; DrawText("loading please wait...",10,10) ; Flip
Local Channel:TChannel = CreateAudioStream( file )

Repeat
	Cls
	If KeyHit(KEY_R) ResumeChannel(Channel)
	If KeyHit(KEY_P) PauseChannel(Channel)
	If KeyHit(KEY_S) StopChannel(Channel)
	If ChannelPlaying(channel)
		DrawText("Streaming...",10,10)
	Else
		DrawText("Stopped...",10,10)
		If KeyHit(KEY_X) Channel = CreateAudioStream( file )
	EndIf
	Flip
Until AppTerminate() Or KeyHit(KEY_ESCAPE)


I just added the x button to start over after stopping. It works, too, but if you press X twice(or more often) after you stop the song it instantly starts over (once).
I just wonder about this queue and why it only happens once and not for subsequently pressing X?

Anyway great fun :)

Thanks again guys!

DirectSound references should now be fixed, thanks GregBUG! (how stupid was that LOL)

North, I think its the KeyHit(KEY_X) causing that as it doesnt get called until the music has stopped playing, check this...
	If ChannelPlaying(channel)
		DrawText("Streaming...",10,10)
		KeyHit(KEY_X) ' flush the x key
	Else
		DrawText("Stopped...",10,10)
		If KeyHit(KEY_X) Channel = CreateAudioStream( file )
	EndIf


steph, that dont sound good mate, does streaming with mod/xm also produce noise/errors? wierd because I did have streaming before in linux without trouble.
I'll have to think about that speed issue.

Seems odd that Max doesnt catch that "cant find interface" error, anyone know if there is a way to force it to compile a perticular module first? otherwise I'm gonna have to join all the modules together.

anyway next version will be up soon.

I've been messing with this on a PPC Mac. One thing I can't figure out is that it seems like if I use CreateAudioStream to create a stream, how do I delete the stream later?

I tried just setting the resulting TChannel to null, but it seems like the stream stays in memory/keeps running, because each time I do this, my app's processor usage increases.

What I'm doing is I'm streaming a song, and then want to stream a different song.

Hi jhanson, good to now it produces sound on the PPC Mac!
Hopefully this fixes that issue. well spotted mate!

New version available! http://code.google.com/p/maxmod/downloads/list

I've removed quite a bit of stuff from modplayer that related to my tracker (ability to create scopes ect) and optimized some parts, seems to have speeded it up quite alot (30% on some mods), just hope it hasnt caused any new playback issues!

Still havent addressed the "Can't find interface for module 'maxmod.amusic'" issue yet, still not sure if its something max should handle, or wether its just bad practice on my part. (probly my fault, i guess)

*EDIT* BTW I added a few mods in a folder call "media", just to make it easier to compare loading times, on the same songs.
(My crappy system loads Rebels.mod in ~5.5 secs)

Hmmm... I'm not really seeing a difference with that particular bug.

Can someone on another platform try to replicate it? Basically, just take North's sample code above, change it to use OpenAL sound, and alternate hitting S and X in rapid succession. Each time you do that, the processor usage inches up. On my poor G4 Mac Mini, it can jump as much as 5% at a time (but is usually around 3%).

Do you have a recommended way for dealing with the audio streams to free them properly?

Just supposed to be the StopChannel command and the object getting garbage collected.

I dont see that on my system, always returns to 0 CPU usage, wonder whats going on? does it go down at all when the stream is stopped?

It does seem to be leaking ~100K each load tho, will look into that.
*EDIT* woah, its leaking like the titanic on some songs, didnt used to do that in previous (pre-openal) versions of maxmod, so should be a easy fix.

New version is up with fixed leakage :)

jhanson, I've adding a print to the delete method of openalaudiostream to see if it is actualy being collected, if you dont mind could you have a look for it poping up for me? I have altered the way it works, so it might even be fixed now.

REDi, whatever you did in version beta6 seems to have fixed the issue. Great job!

And yes, it was printing the message when it was deleting, BUT it doesn't print the message the first time I hit S to stop the stream. It only prints the message from the second time onward.

Bonus! I think the message wont be printed until you press the x key, and the old channel gets overwritten then collected.

Thanks for your help mate!

Just linux to worry about now, suppose i'll have to dig out a spare harddrive.

It compiles fine on my Intel 10.4.11 laptop, but I don't have the time to test it with any actual code. Would someone please upload a simple example that I can try to run?

Edit: I am a moron, ignore my post before the edit if you saw it. (Forgot to switch to OpenAL...)

Works fine for oggs, but will not load mp3s. (I can't remember if it's even supposed to, but I tried.)

Included example mod files also work.

Thanks Diordna! :D

I've removed mp3 support for now, as it used acm for demuxing it only worked on windows OS.

*EDIT* seems ogg streaming in directsound is broken, will fix ASAP.
*EDIT* Fixed! http://code.google.com/p/maxmod/downloads/list

Work's great on my Mac Pro. Is it possible to load then mod like this

incbin "test.mod"

Sound:TSound = LoadSound("incbin::test.mod", True )

I have tested it but would not work?

.

OK. My mistake. Works now!

Hi MainframeOSX, glad its working for ya.

Could anybody comfirm the issues on Linux, I'm having trouble getting both my DVD writers to recognise blank discs, so cant get linux installed :(

*EDIT* finaly got Ubuntu installed! should be able to look into the prob's after work.

Well, got it up and running in ubuntu edgy, seems to be about the same speed loading as in windows, around 5.5 seconds for the rebels.mod!

I can hear a nasty glitch about once a second with the openal audio driver, no matter if its streaming with maxmod or playing as a sample using blitzmax's openal audio driver, sounds perfect under freeaudio though.

Seems openal is bugged on linux! (explains why I couldn't find it in Synaptic Package Manager I guess)

Sorry to just hop in here right in the middle of things, but I wanted to thank REDi for his work. I have not yet had the opportunity to use MaxMod yet, but anyone who is working to improve the state of sound within BlitzMax and maintain cross compatibility is a hero in my book. Keep up the good work, man.

:salute:

*blush* Thanks Tachyon! :)

:Arnold Rimmer salute:

The streaming works very nice, starts play instantly and even use 1% cpu only, very cool, It's MAGIC!

BRL might want to integrate this in and deprecate the old FreeAudio..

Cant get rid of FreeAudio mate, its the only one that works well on linux! I think Skidracer might have a few tricks up his sleeve yet ;)

I missed this thread for some reason. I'd like to say thanks to REDi for MaxMod as it is the only thing I can use in conjunction with sidstream to stream sid chip tunes.

I'll download the new version now and test it. Hopefully it works with the sidstream mod.

:)

Thanks, REDi. This is a very nice mod. I've been testing it in a game I'm working on for a little while now. I'm on a G4 Mac Mini running Tiger, and it works very nicely.

Thanks guys, glad you find it useful!

Amon, Sorry mate (and GMAN) I completely forgot about SID :(
If you replace sidstream.bmx with this it should work fine...
SuperStrict 

Rem
bbdoc: SID Stream for MaxMod
End Rem
Module SID.SIDStream

ModuleInfo "Version: 1.04"
ModuleInfo "Name: SID.SIDStream"
ModuleInfo "Description: MaxMod SID streaming player"
ModuleInfo "License: GPL (libsidplay2 is GPL)"
ModuleInfo "Author: gman"
ModuleInfo "Credit: REDi, author of MaxMod (http://www.redi.me.uk/forum/index.php)"
ModuleInfo "History: 2006/7/16 - GG Initial Release"
ModuleInfo "History: 2006/8/1 - REDi Updated for MaxMod v1.9"
ModuleInfo "History: 2006/8/29 - Updated for MaxMod v1.10 by Matt Smith (thank you)"
ModuleInfo "History: 2006/9/5 - Updated for MaxMod v1.11 by REDi (thank you)"
ModuleInfo "History: 2006/10/19 - Recompiled for MaxMod v1.15"
ModuleInfo "History: 2007/02/19 - Recompiled for MaxMod v1.16 by REDi"

Import MaxMod.aMusic
Import SID.SIDPlay
Import BRL.StandardIO

' This adds it to the MaxMod Loader
MaxModLoader.Create(MaxMod_Loader_SID,"SID ~q.sid~q","sid")
Function MaxMod_Loader_SID:TMusic(File:String)
	Local SID:TMusic = SIDStream.Load(File)
	Return SID
EndFunction

Rem
bbdoc: MaxMod SID Stream
End Rem
Type SIDStream Extends TMusic

	' SIDPlayer pointers
	Field resid:Byte Ptr
	Field tune:Byte Ptr
	Field player:Byte Ptr
	
	Field Track:Short
	Field Bits:Short
	Field Channels:Short
	Field clockSpeed:Int

	Rem
	bbdoc: Loads a SID file and returns an audio sample for playback
	returns: an instance of TAudioSample
	about: Filename => path and name of file to load<BR>
	Track => the track within the file to return a sample for<BR>
	Rate => sample rate to play the sample at<BR>
	format => sample format<BR>
	clockSpeed => SID sample playback clock speed
	EndRem						
	Function Load:SIDStream(Filename:String, Track:Short=1, Rate:Int=44100, format:Int=MM_STEREO16, clockSpeed:Int=SID2_CLOCK_PAL)
			
		Local file:Byte[]=LoadByteArray(Filename)

		Local This:SIDStream = New SIDStream
		
		' make sure we have the file
		If file
			This.clockSpeed=clockSpeed
			
			' load the SID file into the tune
			This.tune=createSidTune()			
			
			If Not This.tune Then RuntimeError "SIDStream.Load(): Unable to create SidTune"
			
			If Not SidTune_Read(This.tune,file,file.length) Then RuntimeError "SIDStream.Load(): Unable To load "+filename
			file=Null
					
			' select the track within the SID file
			If Not This.SelectTrack(Track) Then RuntimeError "SIDStream.Load(): Unable to select track "+Track
										
			This.channels=sid2_mono
			If format=MM_STEREO8 Or format=MM_STEREO16 Then This.channels=sid2_stereo
		
			' bump down to mono if the sample is mono	
			If This.channels=MM_STEREO8 And Not SidTune_IsStereo(This.tune)
				Select format
					Case MM_STEREO8
						format=MM_MONO8
					Case MM_STEREO16
						format=MM_MONO16
				EndSelect
				This.channels=sid2_mono
			EndIf
			
			This.bits=8
			If format<>MM_MONO8 And format<>MM_STEREO8 Then This.bits=16
		 
			This.STREAM_FORMAT=format
			This.Sample_Rate=Rate
			This.bits=16
		
			' create the ReSIDBuilder
			This.resid=createReSIDBuilder("MaxMod Load SID")
			If Not This.resid Then RuntimeError "SIDStream.Load(): Unable to create ReSIDBuilder"
										
			' create the player for decoding
			This.player=createSidPlay2(This.resid)
			
			' set the player options
			If Not SidPlay2_SetFrequency(This.player,rate) Then RuntimeError "SIDStream.Load(): Unable to set rate "+rate
			If Not SidPlay2_SetBits(This.player,This.bits) Then RuntimeError "SIDStream.Load(): Unable to set bits "+This.bits
			If Not SidPlay2_SetPlayback(This.player,This.channels) Then RuntimeError "SIDStream.Load(): Unable to set format "+format
			If Not SidPlay2_SetClockSpeed(This.player,This.clockSpeed) Then RuntimeError "SIDStream.Load(): Unable to set clockSpeed "+This.clockSpeed
			
			' load the tune into the player
			If SidPlay2_Load(This.player,This.tune)<>0 Then RuntimeError "SIDStream.Load(): Unable to load tune into the player"
			
			Return This					
		Else
			Return Null		
		EndIf	
	EndFunction

	Method Stop()
'		Super.Stop()
		SidPlay2_Load(player,tune)
	EndMethod

	Rem
	bbdoc: Returns the current track being played
	End Rem
	Method CurrentTrack:Short()
		Return Track
	EndMethod

	Rem
	bbdoc: Returns the total tracks within the SID
	End Rem
	Method GetTrackCount:Short()
		Return SidTuneInfo_songs(SidTune_getInfo(tune))
	EndMethod

	Rem
	bbdoc: Selects a track within the SID to play
	returns: True if successful
	End Rem
	Method SelectTrack:Int(track:Short=1)
		' select the track within the SID file
		Local playing:Int
		If PlayStatus = True Then playing = True
		If SidTune_SelectSong(tune,track)=track Then 
'			If playing Then Stop
			SidPlay2_Load(player,tune)
			Self.Track=track
'			If playing Then Play
			Return True
		Else
			Return False
		EndIf
	EndMethod

	Method Delete()
		' cleanup the libsidplay objects
		deleteSidPlay2(player)
		deleteSidTune(tune)
		deleteReSIDBuilder(resid)	
	EndMethod
	
	' this method gets called when the buffer needs filling
	Method FillBuffer(SoundData:Int,Length:Int)
		If Not Length Return
		Global count:Int
		If Not SidPlay2_Play(player,Short Ptr(SoundData),Length) Then RuntimeError "SIDStream.FillBuffer(): Unable to process sample data"
		count:+Length												
	EndMethod
	
EndType


Is GMAN still about? havent seem him on here since I've been back.

Don't forget that you put that print statement in there for testing the deletion of the TOpenALAudioStream objects. You probably want to get rid of that at some point.

Yep, thanks jhanson, will be gone in next release.

Hi REDi

Just been having a go with this under 1.28 on Windows. Everything seems a'ok except it throws up an error when you stop a streaming channel:

"Unhandled Exception:Attempt to call abstract method"

This is while streaming an XM file and it does it with your sample source too.

I assume you will be changing stuff with the release of 1.28 but I thought I would point it out anyway.

Will this help at all with recording?

http://www.blitzmax.com/Community/posts.php?topic=72909

I basically know jack shit about audio programming and need to get up to speed for a new project.

Hi Big&, I'm not getting that here with either openal or directsound driver, was this with the beta7 version? will be putting up an update soon.

Anyone else seeing this?

jhocking, I'll see if I can knock up an example for ya mate.
I've not done it with openal before only directsound, but should be able to sort something out for ya.

Thanks man, that would be very helpful!

Here ya go mate, tried to make it as user friendly as pos, hope it helps!
SuperStrict

EnableOpenALAudio()
SetAudioDriver("OpenAL")
Graphics 500,30,0

' create the openal sampler
Local Sampler:TOpenALSampler = TOpenALSampler.Create(44100,SF_STEREO16LE)
Local AudioSample:TAudioSample
Local Sound:TSound 
Local Channel:TChannel
Local mode:Int

Repeat
	Cls
	Select mode
		Case 0 ' idle, wait to start recording
			DrawText("Idle... Press SPACE to start recording",10,10)
			If KeyHit(KEY_SPACE)
				Sampler.Start
				Mode:+1
			EndIf
		Case 1	' record
			DrawText("Recording..."+Sampler.Size+" bytes - Press SPACE to stop",10,10)
			If KeyHit(KEY_SPACE)
				AudioSample = Sampler.Stop()
				Mode:+1
			EndIf
		Case 2	' idle, wait to playback recorded sound
			DrawText("Recorded "+AudioSample.length+" samples - Press SPACE to start playback",10,10)
			If KeyHit(KEY_SPACE)
				Sound = LoadSound(AudioSample)
				Channel = PlaySound(sound)
				Mode:+1
			EndIf
		Case 3	' playing
			DrawText("Playing... Press SPACE to stop playback",10,10)
			If ChannelPlaying(Channel)=False Or KeyHit(KEY_SPACE)
				StopChannel(Channel)
				Mode=0
			EndIf
	EndSelect
	Flip
Until AppTerminate() Or KeyHit(KEY_ESCAPE)

' ---------------------------------------------------------------------------------
' the sampler!

Type TOpenALSampler

	Field ChunkList:TList = New TList
	Field recordedsamplelength:Int
	Field DefaultSpecifier:String 
	Field CaptureDevice:Int
	Field oalFormat:Int
	Field Format:Int
	Field Hertz:Int
	Field Timer:TTimer
	Field Size:Int

	' create a recorder
	Function Create:TOpenALSampler(Hertz:Int=44100,Format:Int=SF_STEREO16LE)
		Local This:TOpenALSampler = New TOpenALSampler 
		This.DefaultSpecifier = String.FromCString(alcGetString(Null, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER)) ; This.OpenALError
		This.Hertz = Hertz
		This.Format = Format
		Select format
			Case SF_MONO8		; This.oalFormat = AL_FORMAT_MONO8
			Case SF_MONO16LE 	; This.oalFormat = AL_FORMAT_MONO16
			Case SF_MONO16BE 	; This.oalFormat = AL_FORMAT_MONO16
			Case SF_STEREO8		; This.oalFormat = AL_FORMAT_STEREO8
			Case SF_STEREO16LE 	; This.oalFormat = AL_FORMAT_STEREO16
			Case SF_STEREO16BE 	; This.oalFormat = AL_FORMAT_STEREO16
		EndSelect
		This.CaptureDevice = alcCaptureOpenDevice(This.DefaultSpecifier,Hertz,This.oalFormat,44100*16) ; This.OpenALError
		Return This
	EndFunction
	
	' start recording
	Method Start()
		If Timer Return
		Timer = CreateTimer(60)
		AddHook EmitEventHook,eventhook,Self
		alcCaptureStart(CaptureDevice)	; OpenALError
	EndMethod

	' stop recording and return a TAudioSample
	Method Stop:TAudioSample()
		StopTimer Timer ; Timer = Null
		RemoveHook EmitEventHook,eventhook,Self
		alcCaptureStop(CaptureDevice) ; OpenALError
		CaptureAudioChunk	' flush remaining audio
		Local samplesbank:TBank
		Local AudioSample:TAudioSample = CreateAudioSample(size/BytesPerSample[format],hertz,format)
		Local bptr:Byte Ptr = AudioSample.samples
		For samplesbank=EachIn ChunkList
			MemCopy(bptr,BankBuf(samplesbank),BankSize(samplesbank))
			bptr:+BankSize(samplesbank)
		Next
		ClearList(ChunkList)
		Size=0
		Return AudioSample
	EndMethod

	Function eventhook:Object(id:Int,data:Object,context:Object)
		Local Sampler:TOpenALSampler = TOpenALSampler(context)
		If Sampler
			Local event:TEvent = TEvent(data)
			If Event.ID=EVENT_TIMERTICK And Event.Source=Sampler.Timer
				Sampler.CaptureAudioChunk
			EndIf
		EndIf
		Return data
	EndFunction

	Method CaptureAudioChunk()
		Local recordedsamplelength:Int
		alcGetIntegerv(CaptureDevice,ALC_CAPTURE_SAMPLES,4,Varptr recordedsamplelength) ; OpenALError
		If recordedsamplelength
			Local samplesbank:TBank = CreateBank(recordedsamplelength*BytesPerSample[format])
			alcCaptureSamples(CaptureDevice,BankBuf(samplesbank),recordedsamplelength) ; OpenALError
			ListAddLast(ChunkList,samplesbank)
			Size:+BankSize(samplesbank)
		EndIf
	EndMethod

	Method OpenALError()
		Local result:Int = alcGetError(CaptureDevice)
		If result<>0 RuntimeError "Sampler OpenAL Error Code = "+result
	EndMethod

EndType


Just create a sampler object and call the Start method to begin recording, when you call the Stop method it returns a TAudioSample for use with LoadSound or SaveOgg ect.

You can record in whatever sample format and hertz you want.

sweeeeeeeet thanks!

No probs mate, I've just updated the code above to fix a minor bug, you might want to take a copy of it again.

Anybody think its worth adding that to maxmod? with a directsound version of course. Please post your yay or nay below :)

REDi: Yeah, it was with beta7. When I get home I will do a clean install of Max and give it a go again.

New version is up, main fix to note sliding math in modplayer.

Please delete old maxmod folder before you install, rebuild modules and docs.

Big&, fingers crossed mate ;)

REDi:

Everything is working now. Didn't do a reinstall, just put the most recent Maxmod in and it works fine :)

Can I be cheeky and ask if there is any way to have a "Set Pattern Number" or a "FMUSIC_SetOrder" as it is in FMOD?
Its just I have loads of different tunes inside one XM file and I have had to go through said XM file and save out all the individual tunes. This is causing some playback problems with Maxmod as I am hacking and slashing away at the module, causing who knows what damage :)

(EDIT: The above cheekiness is to do with streaming.)

Yep, no problem mate. Will get onto that for ya in a tad, just got home from work, so need to wind down a bit first ;)

Big&, Here is a little function to do what you want...
Function SetModPlayerPosition(Channel:TChannel Var, Sequence:Int, Line:Int=0)
	Local Mixer:MaxMod_Mixer = MaxMod_Mixer(TAudioStream(Channel).Music)
	If Not Mixer Return
	TAudioStream(Channel).KeepMusic = True
	StopChannel(Channel)
	Mixer.Seti(MM_SEQUENCE,Sequence)
	Mixer.Seti(MM_LINE,Line)
	Channel = CreateAudioStream(Mixer)
	TAudioStream(Channel).KeepMusic = False
EndFunction

You'll need to download a copy of 1.21 to get it to work properly.

I spent ages trying to work it into maxmod, but because it uses both MaxMod.AudioStream and MaxMod.ModPlayer its a bit awkward, hopefuly a solution will come up soon, otherwise I'm gonna end up having to put it all into one module again :(

anyway this works for now.

*GOBSMACKED*

Brilliant mate, thats top!! Have to wait to get home from work to try it. Damn! Why do we have to work!?! :)

Worked a treat REDi!!!! Put a donation button up or something, definitely worth a beer or three :)

My pleasure Big&

You're a gent, Mines a stella please :o) (button in the docs)

Missed that and done :)

Thank you kind sir, much appreciated!

Nice work! Seems that i will use this in a near future :D

Excellent, give me a shout if you come across any problems mate.

Have anyone of the MAC Users tested the Sidplay.
Here it does not work!

New version of SIDStream.bmx is way up there on this thread.

1.22 is now available, fixes to xm keyoff command and volume envelopes, also added a tiny bit of C++ to speed up mixing a tad (1 second off a 20 second load on my system)

http://code.google.com/p/maxmod/

Guys,

For those interested in the SidPlay streaming, I updated the wrapper to work with v1.22. Copy the following into your Sid.Mod/SidStream.Mod folder:

Sidstream.bmx
SuperStrict 

Rem
bbdoc: SID Stream for MaxMod
End Rem
Module SID.SIDStream

ModuleInfo "Version: 1.05"
ModuleInfo "Name: SID.SIDStream"
ModuleInfo "Description: MaxMod SID streaming player"
ModuleInfo "License: GPL (libsidplay2 is GPL)"
ModuleInfo "Author: gman"
ModuleInfo "Credit: REDi, author of MaxMod (http://www.redi.me.uk/forum/index.php)"
ModuleInfo "History: 2006/7/16 - GG Initial Release"
ModuleInfo "History: 2006/8/1 - REDi Updated for MaxMod v1.9"
ModuleInfo "History: 2006/8/29 - Updated for MaxMod v1.10 by Matt Smith (thank you)"
ModuleInfo "History: 2006/9/5 - Updated for MaxMod v1.11 by REDi (thank you)"
ModuleInfo "History: 2006/10/19 - Recompiled for MaxMod v1.15"
ModuleInfo "History: 2007/02/19 - Recompiled for MaxMod v1.16 by REDi"
ModuleInfo "History: 2008/01/26 - Added Sid for MaxMod v1.22+ by Matt Smith"

Import MAXMOD.AudioStream
Import SID.SIDPlay
Import BRL.Audio

Private
' This adds it to the MaxMod Loader
MaxModLoader.Create(MaxMod_Loader_SID,"SID ~q.sid~q","sid")
Function MaxMod_Loader_SID:TMusic(File:String)
	Local SID:TMusic = SIDStream.Load(File)
	Return SID
EndFunction

Rem
bbdoc: SIDStream (Private - access SidAudioStream instead)
End Rem
Type SIDStream Extends TMusic

	' SIDPlayer pointers
	Field resid:Byte Ptr
	Field tune:Byte Ptr
	Field player:Byte Ptr
	
	Field Track:Short
	Field Bits:Short
	Field Channels:Short
	Field clockSpeed:Int

	Rem
	bbdoc: Loads a SID file and returns an audio sample for playback
	returns: an instance of TAudioSample
	about: Filename => path and name of file to load<BR>
	Track => the track within the file to return a sample for<BR>
	Rate => sample rate to play the sample at<BR>
	format => sample format<BR>
	clockSpeed => SID sample playback clock speed
	EndRem						
	Function Load:SIDStream(FileName:String, Track:Short=1, Rate:Int=44100, format:Int=MM_STEREO16, clockSpeed:Int=SID2_CLOCK_PAL)
			
		Local file:Byte[]=LoadByteArray(FileName)

		Local This:SIDStream = New SIDStream
		
		' make sure we have the file
		If file
			This.clockSpeed=clockSpeed
			
			' load the SID file into the tune
			This.tune=createSidTune()			
			
			If Not This.tune Then RuntimeError "SIDStream.Load(): Unable to create SidTune"
			
			If Not SidTune_Read(This.tune,file,file.length) Then RuntimeError "SIDStream.Load(): Unable To load "+FileName
			file=Null
					
			' select the track within the SID file
			If Not This.SelectTrack(Track) Then RuntimeError "SIDStream.Load(): Unable to select track "+Track
										
			This.channels=sid2_mono
			If format=MM_STEREO8 Or format=MM_STEREO16 Then This.channels=sid2_stereo
		
			' bump down to mono if the sample is mono	
			If This.channels=MM_STEREO8 And Not SidTune_IsStereo(This.tune)
				Select format
					Case MM_STEREO8
						format=MM_MONO8
					Case MM_STEREO16
						format=MM_MONO16
				EndSelect
				This.channels=sid2_mono
			EndIf
			
			This.bits=8
			If format<>MM_MONO8 And format<>MM_STEREO8 Then This.bits=16
		 
			This.STREAM_FORMAT=format
			This.Sample_Rate=Rate
			This.bits=16
		
			' create the ReSIDBuilder
			This.resid=createReSIDBuilder("MaxMod Load SID")
			If Not This.resid Then RuntimeError "SIDStream.Load(): Unable to create ReSIDBuilder"
										
			' create the player for decoding
			This.player=createSidPlay2(This.resid)
			
			' set the player options
			If Not SidPlay2_SetFrequency(This.player,rate) Then RuntimeError "SIDStream.Load(): Unable to set rate "+rate
			If Not SidPlay2_SetBits(This.player,This.bits) Then RuntimeError "SIDStream.Load(): Unable to set bits "+This.bits
			If Not SidPlay2_SetPlayback(This.player,This.channels) Then RuntimeError "SIDStream.Load(): Unable to set format "+format
			If Not SidPlay2_SetClockSpeed(This.player,This.clockSpeed) Then RuntimeError "SIDStream.Load(): Unable to set clockSpeed "+This.clockSpeed
			
			' load the tune into the player
			If SidPlay2_Load(This.player,This.tune)<>0 Then RuntimeError "SIDStream.Load(): Unable to load tune into the player"
			
			Return This					
		Else
			Return Null		
		EndIf	
	EndFunction
	
	Method Play()
		'SidPlay2_Load(player,tune)
		SidPlay2_Play(player,tune,0)
	
	End Method

	Method Stop()
		SidPlay2_Load(player,tune)

	EndMethod

	Rem
	bbdoc: Returns the current track being played
	End Rem
	Method CurrentTrack:Short()
		Return Track
	EndMethod

	Rem
	bbdoc: Returns the total tracks within the SID
	End Rem
	Method GetTrackCount:Short()
		Return SidTuneInfo_songs(SidTune_getInfo(tune))
	EndMethod

	Rem
	bbdoc: Selects a track within the SID to play
	returns: True if successful
	End Rem
	Method SelectTrack:Int(track:Short=1)
		' select the track within the SID file
		Local playing:Int
		If PlayStatus = True Then playing = True
		If SidTune_SelectSong(tune,track)=track Then 
'			If playing Then Stop
			SidPlay2_Load(player,tune)
			Self.Track=track
'			If playing Then Play
			Return True
		Else
			Return False
		EndIf
	EndMethod

	Method Delete()
		' cleanup the libsidplay objects
		deleteSidPlay2(player)
		deleteSidTune(tune)
		deleteReSIDBuilder(resid)	
	EndMethod
	
	' this method gets called when the buffer needs filling
	Method FillBuffer(SoundData:Int,Length:Int)
		If Not Length Return
		Global count:Int
		If Not SidPlay2_Play(player,Short Ptr(SoundData),Length) Then RuntimeError "SIDStream.FillBuffer(): Unable to process sample data"
		count:+Length												
	EndMethod
	
EndType

'Internal properties
Global myStream:SIDStream	
Global myChannel:TChannel
Global paused:Byte

Public
Rem
bbdoc: SidAudioStream
about: A wrapper of the REDi's MaxMod 1.22+ Streamer to play c64 SIDs via gman's SidPlay module.
End Rem
Type SidAudioStream
	
	Rem
	bbdoc: A wrapper to load and play SID files
	returns: status of load
	about: filename => path and name of file to load<BR>
	track => the track within the SID to play<BR>
	playOnLoad => automatically starts the track once sid is loaded
	hertz => audio playback hertz<BR>
	volume => audio playback volume<BR>
	EndRem						
	Method Load:Byte(filename:String,track:Short=1,playOnLoad:Byte=True,volume:Float=1.0,hertz:Float=1.0)
		'Load music and prepare to stream it
		myStream = SIDStream(LoadMusic(filename))
		If (myStream)
			'Validate track and select
			If (track < 1 Or track > GetTrackCount()) Then track = 1
			
			'Load channel (stop for now)
			myChannel = CreateAudioStream(myStream)
			Stop()
			
			'Set other properties
			SetHertz(hertz)
			SetVolume(volume)

			'Select track and play
			SelectTrack(track)
			If (playOnLoad) Then Play()

			'Success
			Return True
			
		Else
			'Failure
			Return False
			
		End If
		
	End Method
	
	Rem
	bbdoc: Plays the current track
	End Rem
	Method Play()
		'Is player paused?, if restart and exit
		If (paused) Then
			myChannel.SetPaused(False)
			Return
			
		End If
		
		'Is channel already playing?, if so exit
		If (myChannel.Playing()) Then Return

		'Start current track
		myChannel = CreateAudioStream(myStream)
		paused = False
		
	End Method
	
	Rem
	bbdoc: Stops the current track
	End Rem
	Method Stop()
		myStream.Stop
		myChannel.Stop
		paused = False
		
	End Method
	
	Rem
	bbdoc: Pauses the current track
	End Rem
	Method Pause()
		myChannel.SetPaused(True)
		paused = True

	End Method
	
	rem
	bbdoc: Restarts the current track from the beginning
	end rem
	Method Restart()
		Stop()
		Play()
		
	End Method
	
	rem
	bbdoc: Determines if the current track is paused 
	endrem
	Method IsPaused:Byte()
		Return paused
		
	End Method
	
	Rem
	bbdoc: Returns the total tracks within the SID
	End Rem
	Method GetTrackCount:Short()
		Return myStream.GetTrackCount()
		
	End Method
	
	Rem
	bbdoc: Returns the current track being played
	End Rem
	Method CurrentTrack:Short()
		Return myStream.CurrentTrack()
		
	End Method
	
	Rem
	bbdoc: Selects a track within the SID to play
	returns: True if successful
	End Rem
	Method SelectTrack:Int(track:Short=1)
		Return myStream.SelectTrack(track)
		
	End Method
	
	Rem
	bbdoc: Sets SID audio playback hertz
	End Rem
	Method SetHertz(Hertz:Float)
		myChannel.SetRate(Hertz)
		
	End Method
	
	Rem
	bbdoc: Sets SID audio playback volume
	End Rem
	Method SetVolume(Volume:Float)
		myChannel.SetVolume(Volume)
		
	End Method
	
	Rem
	bbdoc: Disposes the Audio object
	End Rem
	Method Dispose()
		'Free sid channel
		myChannel.Stop
		myChannel = Null
		
		'Free sid stream
		myStream.Free()
		myStream = Null
		
	End Method
	
EndType



The following example shows you how to use the mod:
' load.bmx

Strict 
Framework BRL.GLMax2D 
Import SID.SIDStream
Graphics 800,600,0 

'Set audio driver
'SetAudioDriver("DirectSound")

'Create sid audio stream object
Local sas:SidAudioStream = New SidAudioStream
sas.Load(RequestFile("Load a sid file"))

Local Pitch# = 1
Repeat 

	Cls 
	DrawText "  ESCAPE = Exit",5,5
	DrawText "   SPACE = Play",5,20
	DrawText "       S = Stop",5,35
	DrawText "       R = Restart",5,50
	DrawText "       P = Pause",5,65
	DrawText " UP/DOWN = Pitch",5,80
	
	DrawText "   PITCH = "+Pitch,5,125

	DrawText "TOTAL TRACKS = "+sas.GetTrackCount(),5,170
	DrawText "       TRACK = "+sas.CurrentTrack(),5,185
	DrawText "  LEFT/RIGHT = Select Track",5,200
	
	If KeyHit(KEY_S) 	 Then sas.Stop()
	If KeyHit(KEY_SPACE) Then sas.Play()
	If KeyHit(KEY_P) 	 Then sas.Pause()
	If KeyHit(KEY_R) 	 Then sas.Restart()
	If KeyDown(KEY_UP)	 Then Pitch:+0.001 ; sas.SetHertz(Pitch)
	If KeyDown(KEY_DOWN) Then Pitch:-0.001 ; sas.SetHertz(Pitch)
	If KeyHit(KEY_LEFT)  Then sas.SelectTrack(sas.CurrentTrack()-1)
	If KeyHit(KEY_RIGHT) Then sas.SelectTrack(sas.CurrentTrack()+1)

	Flip True
	
Until KeyDown(KEY_ESCAPE)

'Tidyup
sas.Dispose()
End



Thanks again to REDi and GMan for the original mods.

Cool, Thanks Matt! :D