roymacdonald / ofxSoundObjects

Simple yet super powerful modular sound architecture for openFrameworks.
Other
90 stars 26 forks source link

bug fixed: matching channels of ofxSoundRecorderObject #56

Open sadmb opened 11 months ago

sadmb commented 11 months ago

Fixed a bug when ofxSoundRecorderObject can't record properly when the number of input channels and output channels are not the same.

Closes #55

roymacdonald commented 11 months ago

Hi. Thanks but this is not the correct fix. It might work for you but it will not render files correctly when used in several other scenarios.

sadmb commented 11 months ago

The problem is that the number of channels for recorder is forced to be changed when it processes audioOut (ofxSoundUtils::checkBuffers).

The channels of recorder should be the same as ofsoundstreamsettings.numInputChannels.

Can you tell me why its working buffer should be changed to the same size as output buffer?

sadmb commented 11 months ago

What I want to do is to record a stereo audio file with playing it on 4 speakers (headphones and stereo speakers) using a device with max 6 input channels and 16 output channels. It seems the working buffer of the recorder is decided not by input buffer but by output buffer so I couldn't make it a success. I've also tried to use ofxSoundMultiplexer but no success so far.

sadmb commented 11 months ago

ofxSoundObject::getNumChannels() always returns the max number of output channels of the output device even when you setup settings.numOutputChannels = 4 so I imagine I have to use ofxSoundOutputMultiplexer instead of ofxSoundOutput when I want to use a part of output channels. But when I try like:

input.getOrCreateChannelGroup({0, 1}).connectTo(recorder).connectTo(mixer).connectTo(output.getOrCreateChannelGroup({0, 1, 2, 3}));

Still it records a sound file with 4 channels and its sound is noisy. I think it's because it only has 2 mics but it records 4 channels so it has silent data for 2 channels out of 4 channels for each frame.

roymacdonald commented 11 months ago

Hi, First thing. Which OS are you using? I develop on macos, so in it the number of out channels you set in the stream setup is the same as in the buffer passed through the signal chain. Not the input. Not sure if it differs on other platforms. This addon works with a pull through scheme, which uses the audio out call back and just pulls from the connected devices upstream. The issue now is that you might want to place the recorder anywhere in the signal chain. so when you use a multiplexer, it will "decouple" the signal from the source or destination, in regards from its number of channels, at least. You can use a multiplexer to record each channel individually, thus it should not be set by the output channel count.

roymacdonald commented 11 months ago

did you take a look to the example-multiFileSoundRecorder? If you use it it should give you the results you want.

sadmb commented 11 months ago

@roymacdonald Thanks for the reply. I use Sonoma 14.1 on a new Mac (M3 Max) with Scarlett4i4 as an audio interface.

the number of out channels you set in the stream setup is the same as in the buffer passed through the signal chain. Not the input. Not sure if it differs on other platforms.

Yes. I know. process(ofxSoundObject &input, ofxSoundObject &output) is called in audioOut(ofxSoundObject &output) which is called through the signal chain starts from output stream so the buffer is resized to the same size as output buffer.

But I believe that the number of channels of the recorded sound file should be the same as the input channels, not the output channels. For example, if you want to record a single channel audio file, you would setup settings.numInputChannels = 1 to record.

Now it is possible to record a single channel audio file only when you would setup settings.numOutputChannels = 1. Or using recorder.connectTo(output.getOrCreateChannelGroup({0})) to connect to a single channel of several output channels. Therefore, It seems it is impossible to record a single channel audio file with a mic and several speakers so far. (Also, it would be impossible to record a multiple channel audio file with several mics and a speaker)

If it is not good to resize theofxSoundRecorderObject::workingBuffer for some reasons, I recommend to have another local buffer to resize to the same size as input buffer to pass to write(ofSoundBuffer& input) because users want to record an audio file with the same number of channels as input channels.

roymacdonald commented 11 months ago

sure. I understand your point. I could add some sort of utility function/class. something like a mix between the input multiplexer and recorder. I don't like the idea of just adding stuff to a class because it might be convenient in some cases where you can still make it without it.

sadmb commented 11 months ago

@roymacdonald I understand it is difficult to change the design which may impact to existing projects. But still, for me, it seems it’s better to design a recorder depends on mics’ settings instead of speakers’ settings even though you can keep it with some external functions. It may not the best way to adjust the buffer with the input steam because the number of input channels connected to a recorder will be different when you use ofxSoundInputMultiplexer instead of ofxSoundInput. But I think you can find a better solution at least to resize it to the input connections instead of the output.

I will use my branch for now because I couldn’t find the way to meet my requirement (recording a stereo audio file with 2mics and 4speakers), but I am happy if you can share your version.

Thanks!

sadmb commented 11 months ago

I've also found ofxSoundRecorderObject is defined as OFX_SOUND_OBJECT_DESTINATION but it doesn't work without output connection. Probably it should be defined as OFX_SOUND_OBJECT_PROCESSOR?