Realtime sound sample manipulation

BlitzMax Forums/BlitzMax Programming/Realtime sound sample manipulation

Difference(Posted 2008) [#1]
I'd like to write to the samplebuffer directly, and have the changes played back the next time the sample loops.

I've done this in PowerBasic in the past with a Windows only solution.

In Blitzmax, it seems manipulating a buffer used in CreateStaticAudioSample(), doesn't yield any results unless i reload the sound.

Is it possible in native Bmax or do I need a lib?


Brucey(Posted 2008) [#2]
You could do it with OpenAL, creating your own audio buffer data as necessary.


Who was John Galt?(Posted 2008) [#3]
I have done it with the FMOD module, but it's a bit of a pain and involves some C programming (unless the garbage collector has improved to the point where the callback could be written in Blitz without bizarre errors, since I last tried.)

I think Taron recently did something similar to what you're attempting, so invade one of his threads and ask.


Taron(Posted 2008) [#4]
Well, well... I'm really just doing hardcore looping by not only reloading a sample piece, but the generating and reloading the whole thing, which is everything but what you'd want. My goal hasn't been to do a realtime synth, because during a game it would only additionally burden the cpu (unless multithreaded and even then I would likely find a better use for the second thread...).

Anyway, I do love the idea of a realtime synth and also keep my eyes open for good suggestions using bmax. I do, however, want to learn more about including c libs and code snippits, since I am natively rather a C guy, yet not in regards to entire applications but rather for writing plugins. I've never done any audio programming, so this is my first time ever. It's remarkably dissimilar to graphics programming, due to the 1 dimentional aspect of it and the need to do many things on the fly in one go. Makes you think differently, but it's great! In the last two weeks I've learned unbelievable amounts about sound programming, but also interface coding and the likes. All stuff I've never done to that extend or at all.

As for Fmod, I think I just don't like to make myself depend on things, particularely if they are somewhat restrictive (license stuff included). Souns paradox for new BlitzMax programmer to say, but well... I hope you know what I mean.

Two things to find out:
- implementing C code
- Basic DirectAudio or OpenAL coding in C

That's all, and I'm sure we'll be ready to rock! 8)


Difference(Posted 2008) [#5]
Thanks guys.

For now it looks like OpenAL or some native Windows stuff if I can dig it out of my archives then.


skidracer(Posted 2008) [#6]
this code should/may still work with freeaudio multimedia drivers:

tfloat synth test


Difference(Posted 2008) [#7]
Thanks skidracer, but I can't get the Freeaudio driver to initialise.

[EDIT]: "Freeaudio Multimedia" does initialise, but nothing happens when I write to the sample buffer after Loadsound has been called

Am I missing something?

Below is my testcode, clipped together from the examples in the other thread.

With "FreeAudio DirectSound" I get the noise when it's unrem'ed and run before LoadSound(), but I can't change the samples in the mainloop.





skidracer(Posted 2008) [#8]
Hi Peter, sorry to waste your time, I'll try and have a look at freeaudio streaming this weekend hopefully.


Difference(Posted 2008) [#9]
Don't be sorry, it's great if you can look into it.

It might very well be me not quite grasping the finer details.

I updated your code like shown below. It runs and readpos returns what looks like valid results to me by casting the channel to a TFreeAudioChannel , but I still get no sound.




REDi(Posted 2008) [#10]
If your interested I'll be releasing the new MaxMod2 module soonish.
A simple example using MaxMod2.CallbackStream works like this ATM...
Import MaxMod2.PortAudio
Import MaxMod2.CallbackStream

Local Chn:TChannel = CreateAudioCallbackStream(New TAudio)
Repeat
	Delay 1
Until ChannelPlaying(Chn)=0

Type TAudio Extends TCallbackStream

	Field p!, p1!

	Method New()
		SampleRate = 11025							' set required samplerate
		Channels   = 1								' set the number of channels
		Bits       = 16							' set bits per channel
	EndMethod

	Method FillBuffer:Int(output:Byte Ptr,size:Int)

		Local AudioPtr:Short Ptr = Short Ptr(output)		' get our pointer to the output
		Local n:Int,av!							' make some local variables
		For n=0 Until size/2						' loop to process the output buffer
			av=Sin( Sin(p1^2)*ATan(p^3)*20000 )*5000	' calculate our audio value
			If p1<1 Then av:*p1						' add a simple fade in
			AudioPtr[n] = av						' apply audio value to output
			p:+0.5 ; p1:+0.00009					' increment for next pass
			If p>1000000 Exit;						' stop when p>1000000
		Next
		Return n*2								' return number a bytes written to output.
												' a return value less than 'size' 
												' causes the stream to stop
	EndMethod

EndType

latency isnt to bad at about a 10th of a second, and of course all the standard TChannel commands work on the stream too.

*EDIT* excuse the borked tabbing


Difference(Posted 2008) [#11]
@REDi : Looks just like what I'm looking for.

How do I set the bufer size?

I'll be looking forward to the release of maxmod2 !
Is there a beta? :-)


REDi(Posted 2008) [#12]
How do I set the bufer size?

The circular buffer size is handled internally and is normally <100 millisecs (depending on audio driver used), but the amount of audio you want to play is up to you, as soon as you return less than the requested amount of audio it assumes you're all done and ends when its finished playing what you've given it, so you can play a couple of millisecs or hours worth :)

Is there a beta? :-)

the first couple of releases are always beta for me, until people stop finding problems ;) I'll hopefully be able to release in a couple of days.


Difference(Posted 2008) [#13]
So if my aim is to play a looping 32ms tone, I'll handle the looping by
writing it at least 1102/353 (3.1'ish) times to the buffer, and remember the loop offset between runs?
(assuming 32ms ~ 353 samples at 11025.)

[EDIT]: Okay, to make it easy on myself, I 'll write it 4 times?... :-)