iOS正弦波生成-可听到咔哒声

iOS正弦波生成-可听到咔哒声,ios,core-audio,audiounit,synthesis,synthesizer,Ios,Core Audio,Audiounit,Synthesis,Synthesizer,我正在为iOS创建合成器。在玩游戏和尝试学习核心音频后,我遇到了一个无法解决的问题。我的正弦波在有规律的间隔上发出咔哒声,我猜这与相位有关。我看过几本关于这个主题的指南和书籍,都表明我做得对 如果有人愿意帮我看一下我的代码,我将不胜感激 static OSStatus renderInput(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 in

我正在为iOS创建合成器。在玩游戏和尝试学习核心音频后,我遇到了一个无法解决的问题。我的正弦波在有规律的间隔上发出咔哒声,我猜这与相位有关。我看过几本关于这个主题的指南和书籍,都表明我做得对

如果有人愿意帮我看一下我的代码,我将不胜感激

static OSStatus renderInput(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData)
{


    // Get a reference to the object that was passed with the callback
    // In this case, the AudioController passed itself so
    // that you can access its data.
    AudioController *THIS = (AudioController*)inRefCon;

    // Get a pointer to the dataBuffer of the AudioBufferList
    AudioSampleType *outA = (AudioSampleType *)ioData->mBuffers[0].mData;

    float freq = THIS->Frequency;   
    float phase = THIS->sinPhase;

    float envValue;
    float sinSignal;

    // The amount the phase changes in  single sample
    double phaseIncrement = 2 * M_PI * freq / kGraphSampleRate;

    // Loop through the callback buffer, generating samples
    for (UInt32 i = 0; i < inNumberFrames; ++i) {       

        sinSignal = sin(phase);

        envValue = THIS->env.tick();

        // Put the sample into the buffer
        // Scale the -1 to 1 values float to
        // -32767 to 32767 and then cast to an integer
        outA[i] = (SInt16)(((sinSignal * 32767.0f) / 2) * envValue);

        phase = phase + phaseIncrement;

        if (phase >= (2 * M_PI * freq)) {
            phase = phase - (2 * M_PI * freq);
        }
    }

    // Store the phase for the next callback.
    THIS->sinPhase = phase;

    return noErr;
}
静态OSStatus renderInput(void*inRefCon,AudioUnitRenderActionFlags*ioActionFlags,const AudioTimeStamp*inTimeStamp,UInt32 inbunsumber,UInt32 inNumberFrames,AudioBufferList*ioData)
{
//获取与回调一起传递的对象的引用
//在这种情况下,AudioController将其自身传递为so
//您可以访问它的数据。
AudioController*此=(AudioController*)在Refcon中;
//获取指向AudioBufferList的数据缓冲区的指针
AudioSampleType*outA=(AudioSampleType*)ioData->mBuffers[0].mData;
浮动频率=此->频率;
浮动相位=此->正弦相位;
浮点数;
浮动正弦信号;
//单个样品中的相变量
双相增量=2*M_PI*freq/kg采样率;
//循环通过回调缓冲区,生成样本
对于(UInt32 i=0;ienv.tick();
//将样品放入缓冲液中
//将-1到1的值按比例浮动到
//-32767到32767,然后强制转换为整数
outA[i]=(SInt16)((sinSignal*32767.0f)/2)*环境值;
相位=相位+相位增量;
如果(相位>=(2*M_PI*freq)){
相位=相位-(2*M_PI*freq);
}
}
//存储下一次回调的阶段。
此->正弦相位=相位;
返回noErr;
}

相位可能在错误点溢出

替换此项:

if (phase >= (2 * M_PI * freq)) {
    phase = phase - (2 * M_PI * freq); 
} 


如果频率不完全是整数值,则此行:

phase = phase - (2 * M_PI * freq);

将以不等于2pi的量调整和旋转相位,从而产生不连续性。

解决此类问题的一种很好的调试方法是在示波器或波形编辑器中查看音频。了解点击发生的确切时间和频率通常会提供一些关于点击发生原因的线索

同样的技术也可用于非“音频”信号,如信封发生器等。只需确保您将扬声器音量调低

phase = phase - (2 * M_PI * freq);