gapless sample replay - how to do?

Discuss any general programming issues here
Post Reply
zylesea
Posts: 227
Joined: Tue Feb 16, 2010 12:50 am
Location: Westfalen/Germany
Contact:

gapless sample replay - how to do?

Post by zylesea »

I am writing a program where I calulate some data and replay that as sample.
But the replay is stuttering.
Let's assume the basic layout of the program looks like that:

Code: Select all


Function p_DoSomethingComputingIntensive()
... [many operations]...
EndFunction 

Function p_CalculateSample()
  For k=0 To 2499
    noise[k]=Rnd (max_noise)
  Next   
 CreateSample(1, noise, 10000) 
EndFunction 

Function p_mainthing()
 p_DoSomethingComputingIntensive()
 p_CalculateSample()
 PlaySample (1)
EndFunction

SetInterval(0, p_mainthing, 125)

Repeat
    WaitEvent
Forever  
The buffer for the sample is as big as required for a 125 ms sample. A bigger buffer won't cure the stuttering. I guess the prob is that the sample replay is not an operation leaving the main loop once triggered but keeps the loop locked for the time of the replay. All operations of one loop repetition take less than 125 ms (cpu load at about 35%), hence a gapless should be possible somehow and I think more or less every program doing sample replay does it. But I don't know how to achieve that.
User avatar
airsoftsoftwair
Posts: 5433
Joined: Fri Feb 12, 2010 2:33 pm
Location: Germany
Contact:

Re: gapless sample replay - how to do?

Post by airsoftsoftwair »

I'm afraid that's currently not possible. We would need a new API to support playback of dynamically generated PCM data. For example, something like

Code: Select all

CreateDynamicMusic(1, p_StreamFunc, 44100)
PlayMusic(1)
Hollywood would call p_StreamFunc() every second and p_StreamFunc() would have to return the hertz number of new PCM samples in a table. But it's quite difficult to support such a functionality because sound playback is lowlevel stuff and the implementation is very different on each platform Hollywood supports, so it's likely to take a lot of time.
User avatar
airsoftsoftwair
Posts: 5433
Joined: Fri Feb 12, 2010 2:33 pm
Location: Germany
Contact:

Re: gapless sample replay - how to do?

Post by airsoftsoftwair »

Hollywood 5.0 now supports gapless sample replay. Have a look at the Synthesizer example.
zylesea
Posts: 227
Joined: Tue Feb 16, 2010 12:50 am
Location: Westfalen/Germany
Contact:

Re: gapless sample replay - how to do?

Post by zylesea »

Thanks Andreas!
Daumen hoch & super Sache!
Will place an order within the very next days.
And the network thing is also cool. And the doublebuffering. And the vector things. And the #?
The list is really long and pretty impressive!
zylesea
Posts: 227
Joined: Tue Feb 16, 2010 12:50 am
Location: Westfalen/Germany
Contact:

Re: gapless sample replay - how to do?

Post by zylesea »

Well, I have issues with a delay during gapless replay I cannot explain. The changes in data providing the stream are affecting the acual stream with quite a delay (1-2s). Just look to the little example code provided below.
Dunno why that is the case. If you press the button (the red box), it takes a while until the audio changes, albeit the box changes its colour rather immediaely. I don't understand what makes that delay. I also know that it is possible to modify the audio output realtime, since I did that already. Unfortunately I lost that sourcecode (I overwrote it by accident) and now I don't remember what did. Must have been something trivial I guess. Some parameter of FillMusicBuffer() maybe? I appreciate any help.

Code: Select all

ampx=10
ampx=10      
bla=False
mtoggle=True
noise={2500}
;*** FUNCTIONS ***** FUNCTIONS **** FUNCTIONS **** FUNCTIONS ****
Function p_makenoise()
    If mtoggle=True
        ampy=1
        ampz=1
        Box (100, 100, 50, 50, #BLUE)
        Else
            ampy=0.5
            ampz=0.5
            Box (100, 100, 50, 50, #RED)
    EndIf
    For k=0 To 2500
    noise[k]=Sin(k/ampx)*60*Ampz+Cos(k/ampy/2)*60*Ampz
    Next
    CreateSample(1, noise, 10000)
    bla=1
EndFunction

Function p_dobutton1()    
    mtoggle=  ~mtoggle
    p_makenoise()
EndFunction

Function p_FillMusicBuffer()
If bla >0
      FillMusicBuffer  (1, "sample", 2500, {id=1} )
	Else
		FillMusicBuffer(1, "Mute", 500)
	EndIf
EndFunction

Box (100, 100, 50, 50, #RED)
evtmatch1={ OnMouseUp = p_dobutton1 }
MakeButton (1, #SIMPLEBUTTON,100, 100, 50, 50, evtmatch1)

InstallEventHandler({FillMusicBuffer = p_FillMusicBuffer} )
CreateMusic (1, 10000, #MONO8)
PlayMusic (1) 
User avatar
airsoftsoftwair
Posts: 5433
Joined: Fri Feb 12, 2010 2:33 pm
Location: Germany
Contact:

Re: gapless sample replay - how to do?

Post by airsoftsoftwair »

The delay is caused by the internal buffering. I don't think there's currently a way around this so I'm wondering how you did achieve the realtime changes? Maybe it is possible to feed only very few samples to FillMusicBuffer(), i.e. less than requested. But I'm not sure if this will work at all.

I'll think about how this problem could be worked around more elegantly for the next update.
zylesea
Posts: 227
Joined: Tue Feb 16, 2010 12:50 am
Location: Westfalen/Germany
Contact:

Re: gapless sample replay - how to do?

Post by zylesea »

Andreas wrote:The delay is caused by the internal buffering. I don't think there's currently a way around this so I'm wondering how you did achieve the realtime changes? Maybe it is possible to feed only very few samples to FillMusicBuffer(), i.e. less than requested. But I'm not sure if this will work at all.

I'll think about how this problem could be worked around more elegantly for the next update.
Thanks for the reply. It's really a pity that I lost that sourcecode (I overwrote the actual file by accident with an empty one before I made a back up copy of that. Then left the project for a few weeks and forgot what I actually did.
I still have the binaries (win/morphos) at http://via.i-networx.de/Simephys/about.htm though - the sound there is in sync with the oscilloscope and more or less real time. I am rather sure my source to feed FillMusicBuffer was not very small, but held enough data for 1/4 or 1/8 of a second.

I think some circular buffer for audio streams would be cool. You don't need to wait for flushing or terminating the buffer when writing new content. However, I don't know how that could work without pointers.
Gosh, if I only knew how I did it a few weeks ago...
zylesea
Posts: 227
Joined: Tue Feb 16, 2010 12:50 am
Location: Westfalen/Germany
Contact:

Re: gapless sample replay - how to do?

Post by zylesea »

Last night I remembered my trick. I actually kind of cheated: The sound I need is a continous and rather random background plus some temporal precise events. Since backgrund and these events aren't temporally tightly coupled I just splitted them. I did a gapless replay of the background (with the buffer delay) and played single samples directly on top of that. Works!
Post Reply