COCKOS
CONFEDERATED FORUMS
Cockos : REAPER : NINJAM : Forums
Forum Home : Register : FAQ : Members List : Search :

Go Back   Cockos Incorporated Forums > Other Software Discussion > WDL users forum

Reply
 
Thread Tools Display Modes
Old 06-20-2015, 04:37 PM   #1
mviljamaa
Human being with feelings
 
Join Date: Jun 2015
Posts: 348
Default Audio processing in processDoubleReplacing works relative to host playhead?

I have a plug-in that simply reads audio into a buffer and currently also does a Hamming window on it, then outputs it.

What I noticed in my current implementation is that my plug-in seems to only work when the input file starts are aligned in the host exactly at the sizes of the buffers. In this case 1024 samples (or 2048 or 3072 and so on).

See picture in attachments. It's like my plug-in works _relative_ to the host sample position and not based on how many samples of input audio it got. The 3rd track is simply the first one moved forward and the 4th is the plug-in applied to that one. The 4th track cuts track 2 exactly at the amount of samples that's the difference between tracks 1 and 3.

Any ideas? I'm pretty much just reading nFrames in.
I was thinking of whether I need to check for silence or something and not read anything to the buffers if the input is just silence.

Is nFrames == 0 when there's no audio?
Are the in** and out** buffers empty or what if there's no audio input?
Attached Images
File Type: jpg Capture (5).jpg (25.5 KB, 368 views)

Last edited by mviljamaa; 06-21-2015 at 10:02 AM.
mviljamaa is offline   Reply With Quote
Old 06-21-2015, 05:09 AM   #2
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,652
Default

Quote:
Originally Posted by mviljamaa View Post
I'm pretty much just reading nFrames in.
I was thinking of whether I need to check for silence or something and not read anything to the buffers if the input is just silence.

Is nFrames == 0 when there's no audio?
Are the in** and out** buffers empty or what if there's no audio input?
No. When there is "no audio" your plug-in gets fed zeros in its input buffers. If there really is nothing for your plug-in to do (e.g. when it is bypassed), then your ProcessDoubleReplacing() is simply not called at all.

Quote:
Originally Posted by mviljamaa View Post
Any ideas?
Well, it is hard to say without diving really deep into your code, but I think what is missing is that your internal input and output buffers should be asynchronous FIFO queues, which I don't think they are right now. Consider this typical scenario, where the host happens to feed you blocks of 63 samples, but you want to process blocks of 64 samples:

1. The host sends 63 samples, so add them to the input queue.
2. You need 64 samples, so you can't process them yet.
3. The output queue is still empty, so output 63 initial zeros.
4. The host sends 63 samples, so add them to the input queue.
5. Process 64 samples (63 from step 1 + 1 from step 4), remove these from the input queue, and add 64 processed samples to the output queue.
6. The input queue now holds 63+63-64=62 samples, which is too little to process another block (if it would be enough, then you would have to repeat step 5).
7. There are more than 63 samples in the output queue, so thee is no need for initial zeros anymore.
8. Output 63 samples, and remove these from the output queue.

Notice how after step 8 there will be 1 sample left in the output queue, which we will output the next ProcessDoubleReplacing() call. I don't see how your current code would handle such leftovers.

I guess I could hack together an example that does all this if you think that would help...

Last edited by Tale; 06-25-2015 at 04:31 PM. Reason: Fixed typos
Tale is offline   Reply With Quote
Old 06-21-2015, 06:39 AM   #3
mviljamaa
Human being with feelings
 
Join Date: Jun 2015
Posts: 348
Default

Quote:
Originally Posted by Tale View Post
No. When there is "no audio" your plug-in either gets feeded zeros in its input buffers. If there really is nothing for your plug-in to do (e.g. when it is bypassed), then your ProcessDoubleReplacing() is simply not called at all.


Well, it is hard to say without diving really deep into your code, but I think what is missing is that your internal input and output buffers should be asynchronous FIFO queues, which I don't think they are right now. Consider this typical scenario, where the host happens to feed you blocks of 63 samples, but you want to process blocks of 64 samples:

1. The host sends 63 samples, so add them to the input queue.
2. You need 64 samples, so you can't process them yet.
3. The output queue is still empty, so output 63 initial zeros.
4. The host sends 63 samples, so add them to the input queue.
5. Process 64 samples (63 from step 1 + 1 from step 4), remove these from the input queue, and add 64 processed samples to the output queue.
6. The input queue now holds 63+63-64=62 samples, which is too little to process another block (if it would be enough, then you would have to repeat step 5).
7. There are more than 63 samples in the output queue, so thee is no need for initial zeros anymore.
8. Output 63 samples, and remove these from the output queue.

Notice how after step 8 there will be 1 sample left in the output queue, which we will output the next ProcessDoubleReplacing() call. I don't see how your current code would handle such leftovers.

I guess I could hack together an example that does all this if you think that would help...
That's what my code is supposed to do. May have to rewrite though, if it's really the code that's wrong (I've tested it on arrays of 1.0s though and it seemed to work there exactly as needed). Could simplify it though.

Is the nFrames == 0 checking trusthworthy? I assume that it should be zero, when the playhead isn't passing over that sinewave file.

Last edited by mviljamaa; 06-21-2015 at 10:03 AM.
mviljamaa is offline   Reply With Quote
Old 06-21-2015, 07:46 AM   #4
Xenakios
Human being with feelings
 
Xenakios's Avatar
 
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
Default

Quote:
Originally Posted by mviljamaa View Post
(I was reasoning that it was because the nFrames aligned exactly as the buffer size divided by some even number, so that there's never buffer overflow).
Never assume anything like that. Depending on the operating system, audio hardware and the host application, the number can be pretty much anything. It's not guaranteed to be an even number or a power-of-2 number. It may also change between calls to the plugin. You need to be prepared to handle all that.
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.
Xenakios is offline   Reply With Quote
Old 06-21-2015, 08:01 AM   #5
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,652
Default

I'm sorry, but I just don't know how to better explain this... Do you know what a FIFO queue is? If not, then look it up on Wikipedia or something, and then please re-read my explanation (here as well as in the other topic).

If you do know, then I would suggest implementing them instead of using simple buffers, e.g.:

Quote:
Originally Posted by mviljamaa View Post
Here, first output the remaining samples from the outputBuffer (before we can replace it).
You can't do that, because your output queue could hold more than nFrames samples. And you should not replace it, but rather add samples to it, which is why you need a queue.

Quote:
Originally Posted by mviljamaa View Post
Is the nFrames == 0 checking trusthworthy? I assume that it should be zero, when the playhead isn't passing over that sinewave file.
This is not relevant, but yeah, I do think your code should be able to handle nFrames == 0. However, there are probably not many hosts that will actually call your ProcessDoubleReplacing() with nFrames == 0, because then they could just as well not call it at all.

Last edited by Tale; 06-25-2015 at 04:33 PM. Reason: Fixed typos
Tale is offline   Reply With Quote
Old 06-21-2015, 10:02 AM   #6
mviljamaa
Human being with feelings
 
Join Date: Jun 2015
Posts: 348
Default

Ok, here's a significantly simplified code that does the same as the original one (lol?) and I still get the same problem.
Now it should be pretty obvious to spot, where the error is?

http://pasteguru.com/14516

Could it be related to the in** and out** pointers? I'm assuming that they always start at 0 (i.e. they're of the size [channel][nFrames]) when the processDoubleReplacing is called, but might it be that they don't, i.e. they're accumulated between processDoubleReplacing calls? So at some processDoubleCall the incoming nFrames may start from in[channel][s], s > 0, rather than in[channel][0].

Last edited by mviljamaa; 06-21-2015 at 10:22 AM.
mviljamaa is offline   Reply With Quote
Old 06-21-2015, 10:45 AM   #7
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,652
Default

Quote:
Originally Posted by mviljamaa View Post
Ok, here's a significantly simplified code that does the same as the original one (lol?) and I still get the same problem.
Now it should be pretty obvious to spot, where the error is?

http://pasteguru.com/14516
Sure. Implement FIFO queues (i.e. a buffer with head and tail) instead of plain buffers...

Quote:
Originally Posted by mviljamaa View Post
Could it be related to the in** and out** pointers? I'm assuming that they always start at 0 (i.e. they're of the size [channel][nFrames]) when the processDoubleReplacing is called, but might it be that they don't, i.e. they're accumulated between processDoubleReplacing calls? So at some processDoubleCall the incoming nFrames may start from in[channel][s], s > 0, rather than in[channel][0].
You assume correctly, they always start at 0.
Tale is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 02:04 PM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.