[英]iOS - Accessing generated signal from Audio Unit render callback
我有一個iOS / Objective-C程序,當按下按鈕時,該程序使用單個音頻單元播放生成的信號。 我想添加以下功能:
a)第一次按下按鈕時,會以某種數字數組的形式生成信號。
b)然后音頻開始,渲染回調訪問(並播放)生成的信號。
給定我當前的代碼,我覺得這些增加只是幾行,但是我在語法,使用哪種變量類型,如何跟蹤當前樣本等方面遇到麻煩。 我已經包含了相關代碼,因為它是:
按鈕按下:
- (IBAction)startPressed:(id)sender {
[self setupAudioPlayer];
[self createSignal];
[self playAudio];
}
setupAudioPlayer中的一行:
input.inputProcRefCon=&mySignal; // mySignal is an instance var
音頻創建:
-(void)createSignal{
int beepLength=0.020*Fs; // Fs is sampling frequency
float beepFrequency=440; // Hz
// Declare some kind of numeric array "mySignal", which is an instance var.
mySignal=...?
// Generate audio signal (pure tone)
for (int i=1; i<=beepLength; i++) {
float t=i/Fs;
mySignal[i]=sinf(2*M_PI*beepFrequency*t);
}
}
渲染回調:
OSStatus RenderTone(
void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData)
{
const int channel1 = 0;
Float32 *buffer = (Float32 *)ioData->mBuffers[channel1].mData;
// This is where things get hazy
Float32 *mySignal=(Float32 *)inRefCon;
for (UInt32 frame = 0; frame < inNumberFrames; frame++)
{
buffer[frame]=mySignal[?];
}
return noErr;
}
因此,總結一下我的問題:應該如何定義mySignal? 如何從RenderTone訪問此實例變量(我上面的“朦朧”代碼只是一個猜測)? 如何在RenderTone中跟蹤當前樣本? 這種方法還有其他遺漏/奇怪的地方嗎?
感謝您的閱讀和任何幫助,非常感謝!
(我已經看到了示例代碼,該示例代碼將對視圖控制器實例的引用傳遞到render回調中,然后以這種方式訪問實例變量。但是,也許是錯誤地,我在其他地方讀到,這不是好形式,因為它可能涉及太多計時要求如此嚴格的回調的計算開銷。)
由於您是根據代數函數生成幀的,所以為什么不簡單遵循Matt Gallagher的示例呢? 簡而言之:只需將函數移到render回調內,並通過vc實例傳遞參數。
一般來說,您的選擇僅限於將數據傳遞給具有預定義格式的回調。 我可能是在目標C中以良好形式提供建議的最后一個人,但是使用全局變量的方法是少數。
您可以將mySignal
數組(或頻率)作為全局mySignal
傳遞。 不是最“優雅”的面向對象解決方案,而是一種可以避免所有OO麻煩開銷的解決方案。 似乎僅適合使用基於C的解決方案,因為render回調基於C函數。
至於“跟蹤”,不是很清楚您的意思,但是在我自己的生成音調的工作中,我已經用音調長度(以幀周期=長度為秒* Fs
或sampleRate
初始化了一個remainingCycles
周期)進行全局設置調用),並減少每次通過frame
循環的次數; 當數字為零時,您將結束鈴聲。 (當然,您可以使用實例變量代替全局變量。)
也許這違反了面向對象編碼的佳能,但是最終,您只需要完成工作即可。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.