I'm using AUGraph
with different audio units in it, one of them is of type kAudioUnitType_FormatConverter
, and subtype kAudioUnitSubType_NewTimePitch
.
I'm trying to change the kNewTimePitchParam_Rate
parameter on it.
It does work in some way, but when I reset the parameter to the value 1.0 (no change rate) I still get pitch variation in audio. I'm trying to understand how to do that properly.
I'm doing this live in my application, directly calling the AudioUnitSetParameter()
function :
- (void)setTempo:(float)value {
OSStatus err = noErr;
err = AudioUnitSetParameter(tempoUnit, kNewTimePitchParam_Rate, kAudioUnitScope_Global, 0, (Float32)value, 0);
if (err != noErr) {
NSLog(@"Could not set tempo unit rate: %d", (int)err);
}
}
Is it the correct way to do it ? It's an iOS application, are there better ways to achieve this ?
Related question: here
EDIT
After digging around and logging, here is what I found :
First here's the complete graph structure :
AudioUnitGraph 0xDF5046:
Member Nodes:
node 1: 'auou' 'rioc' 'appl', instance 0x170837a80 O I
node 2: 'aufc' 'nutp' 'appl', instance 0x170634f20 O I
node 3: 'aufc' 'nutp' 'appl', instance 0x170a23140 O I
node 4: 'aufc' 'nutp' 'appl', instance 0x17083b700 O I
node 5: 'aumx' 'mcmx' 'appl', instance 0x17063bc80 O I
node 6: 'aumx' 'mcmx' 'appl', instance 0x174626da0 O I
node 7: 'aumx' 'mcmx' 'appl', instance 0x17063bd60 O I
Connections:
node 6 bus 0 => node 4 bus 0 [ 2 ch, 44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved]
node 5 bus 0 => node 3 bus 0 [ 2 ch, 44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved]
node 4 bus 0 => node 7 bus 0 [ 2 ch, 44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved]
node 3 bus 0 => node 7 bus 1 [ 2 ch, 44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved]
node 7 bus 0 => node 2 bus 0 [ 2 ch, 44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved]
node 2 bus 0 => node 1 bus 0 [ 2 ch, 44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved]
Input Callbacks:
{0x100a31764, 0x1706df330} => node 5 bus 0 [2 ch, 44100 Hz]
{0x100a31764, 0x1706df250} => node 5 bus 1 [2 ch, 44100 Hz]
{0x100a31764, 0x1706dccb0} => node 5 bus 2 [2 ch, 44100 Hz]
{0x100a31764, 0x1706dda40} => node 5 bus 3 [2 ch, 44100 Hz]
{0x100a31764, 0x1706dcc40} => node 5 bus 4 [2 ch, 44100 Hz]
{0x100a31764, 0x1706dca80} => node 5 bus 5 [2 ch, 44100 Hz]
{0x100a31764, 0x1706dcaf0} => node 5 bus 6 [2 ch, 44100 Hz]
{0x100a31764, 0x1706df2c0} => node 5 bus 7 [2 ch, 44100 Hz]
{0x100a31764, 0x1706dce00} => node 5 bus 8 [2 ch, 44100 Hz]
{0x100a31764, 0x1706ddb90} => node 5 bus 9 [2 ch, 44100 Hz]
{0x100a31764, 0x1706dddc0} => node 5 bus 10 [2 ch, 44100 Hz]
{0x100a31764, 0x1708c0c40} => node 6 bus 0 [2 ch, 44100 Hz]
{0x100a31764, 0x1706df410} => node 6 bus 1 [2 ch, 44100 Hz]
{0x100a31764, 0x1706ddab0} => node 6 bus 2 [2 ch, 44100 Hz]
CurrentState:
mLastUpdateError=0, eventsToProcess=F, isInitialized=T, isRunning=T (1)
At the far left of the graph, there are to multi channel mixers, each followed by an audio unit new time pitch (pitch modulation), then a mixer that receive audio data from the two, and finally the tempo audio unit.
I configure each mixer at the left with render callbacks.
At first I thought that each callback would be called one after the other, requesting X frames of audio data for a same audio timestamp, but it happens that after changing the rate of the tempo unit, frames aren't requested in order anymore. It doesn't happen with default rate of 1.0.
Here's the output logging with default rate of 1.0 :
0 -> 1024 / 7785692434.000000 (0)
1 -> 1024 / 7785692434.000000 (0)
11 -> 1024 / 7785692434.000000 (0)
2 -> 1024 / 7785692434.000000 (0)
3 -> 1024 / 7785692434.000000 (0)
4 -> 1024 / 7785692434.000000 (0)
5 -> 1024 / 7785692434.000000 (0)
6 -> 1024 / 7785692434.000000 (0)
7 -> 1024 / 7785692434.000000 (0)
8 -> 1024 / 7785692434.000000 (0)
9 -> 1024 / 7785692434.000000 (0)
10 -> 1024 / 7785692434.000000 (0)
12 -> 1024 / 7785692434.000000 (0)
13 -> 1024 / 7785692434.000000 (0)
------------ advance to 1024 --------------
0 -> 1024 / 7785693458.000000 (0)
1 -> 1024 / 7785693458.000000 (0)
11 -> 1024 / 7785693458.000000 (0)
2 -> 1024 / 7785693458.000000 (0)
3 -> 1024 / 7785693458.000000 (0)
4 -> 1024 / 7785693458.000000 (0)
5 -> 1024 / 7785693458.000000 (0)
6 -> 1024 / 7785693458.000000 (0)
7 -> 1024 / 7785693458.000000 (0)
8 -> 1024 / 7785693458.000000 (0)
9 -> 1024 / 7785693458.000000 (0)
10 -> 1024 / 7785693458.000000 (0)
12 -> 1024 / 7785693458.000000 (0)
13 -> 1024 / 7785693458.000000 (0)
So everything is perfectly fine here, callback number 0, 1 and 11 are put on one mixer, the rest on the other mixer (the large float on the right is the callback audio timestamp sample time).
Now when I change to a higher rate :
0 -> 1156 / 7785775378.000000 (0)
1 -> 1156 / 7785775378.000000 (0)
11 -> 1156 / 7785775378.000000 (0)
------------ advance to 84100 --------------
0 -> 380 / 7785776534.000000 (0)
1 -> 380 / 7785776534.000000 (0)
11 -> 380 / 7785776534.000000 (0)
------------ advance to 84480 --------------
2 -> 1156 / 7785775378.000000 (0)
3 -> 1156 / 7785775378.000000 (0)
4 -> 1156 / 7785775378.000000 (0)
5 -> 1156 / 7785775378.000000 (0)
6 -> 1156 / 7785775378.000000 (0)
7 -> 1156 / 7785775378.000000 (0)
8 -> 1156 / 7785775378.000000 (0)
9 -> 1156 / 7785775378.000000 (0)
10 -> 1156 / 7785775378.000000 (0)
12 -> 1156 / 7785775378.000000 (0)
13 -> 1156 / 7785775378.000000 (0)
------------ advance to 85636 --------------
2 -> 380 / 7785776534.000000 (0)
3 -> 380 / 7785776534.000000 (0)
4 -> 380 / 7785776534.000000 (0)
5 -> 380 / 7785776534.000000 (0)
6 -> 380 / 7785776534.000000 (0)
7 -> 380 / 7785776534.000000 (0)
8 -> 380 / 7785776534.000000 (0)
9 -> 380 / 7785776534.000000 (0)
10 -> 380 / 7785776534.000000 (0)
12 -> 380 / 7785776534.000000 (0)
13 -> 380 / 7785776534.000000 (0)
Audio data is requested in a different order, twice for the first 3 callbacks, then for the rest.
Can anyone confirm what I observe is expected ?
User contributions licensed under CC BY-SA 3.0