帮助在iPhone上实时更新声音

时间:2010-11-27 23:09:10

标签: iphone objective-c audio ios4 audiounit

我的问题有点棘手,而且我并没有完全体验过(我可能会说错了一些条款),所以这里就是这样。 我正在声明一个名为“歌手”的对象的实例。该实例被称为“singer1”。 “singer1”产生音频信号。现在,以下是确定音频信号细节的代码:

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

//Singer *me = (Singer *)inRefCon;

static int phase = 0;

for(UInt32 i = 0; i < ioData->mNumberBuffers; i++) {

    int samples = ioData->mBuffers[i].mDataByteSize / sizeof(SInt16);

    SInt16 values[samples];

    float waves;
    float volume=.5;

    for(int j = 0; j < samples; j++) {


        waves = 0;


        waves += sin(kWaveform * 600 * phase)*volume;
        waves += sin(kWaveform * 400 * phase)*volume;
        waves += sin(kWaveform * 200 * phase)*volume;
        waves += sin(kWaveform * 100 * phase)*volume;            

        waves *= 32500 / 4; // <--------- make sure to divide by how many waves you're stacking

        values[j] = (SInt16)waves;
        values[j] += values[j]<<16;

        phase++;

    }

    memcpy(ioData->mBuffers[i].mData, values, samples * sizeof(SInt16));

}

return noErr;

}

其中99%是借来的代码,所以我只对它的工作原理有了基本的了解(我不知道OSStatus类或方法或者其他什么。但是,你会看到这4行600,400那些,200和100?它们决定频率。现在,我想做的(现在)是在那里插入我自己的变量来代替常量,我可以随心所欲地改变。这个变量叫做“fr1” “。”fr1“在头文件中声明,但如果我尝试编译,我得到一个关于”fr1“未声明的错误。目前,我修复此问题的技巧如下:在#import内容的正下方,我添加这条线

fr1=0.0;//any number will work properly

这种工作,因为代码将编译并且singer1.fr1实际上将改变值,如果我告诉它。问题现在是这样的:A)即使这个编译并且指定的音调将播放(0.0是没有音调),我得到警告“数据定义没有类型或存储类”和“类型默认为'int'在声明中'FR1'”。我打赌这是因为由于某种原因,它没有在头文件中看到我之前的声明(作为一个浮点数)。但是,如果我离开这一行,代码将无法编译,因为“fr1未声明”。 B)仅仅因为我更改fr1的值并不意味着singer1将更新存储在“playbackcallback”变量中的值或者更新输出缓冲区的任何内容。也许这可以通过不同的编码来解决? C)即使这确实有效,在暂停/播放音频时仍然存在明显的“差距”,我需要消除这种差距。这可能意味着对代码进行彻底检查,以便我可以“动态”插入新值而不会中断任何内容。然而,我正在经历所有这些努力发布的原因是因为这种方法完全符合我的要求(我可以用数学方法计算一个值,直接进入DAC,这意味着我可以在将来使用它来制作三角形,方形等很容易挥手)。我已经将Singer.h和.m上传到了pastebin,为您带来愉快的乐趣,也许他们会有所帮助。抱歉,我无法发布2个HTML标记,因此这里是完整链接。 (http://pastebin.com/ewhKW2Tk) (http://pastebin.com/CNAT4gFv)

所以,TL; DR,我真正想做的就是能够定义4个波的当前方程/值并经常重新定义它们而声音没有间隙。 谢谢。 (对不起,如果帖子混乱或偏离轨道,我很确定它确实如此。)

1 个答案:

答案 0 :(得分:1)

我的理解是每次需要重新填充缓冲区时都会调用回调函数。因此,更改fr1..fr4将改变波形,但仅在缓冲区更新时。您不需要停止并重新启动声音来进行更改,但如果更改fr值,您会注意到音色的突然变化。为了在音色上获得平滑过渡,你必须实现一些能够随着时间的推移平滑地改变fr值的东西。通过调整缓冲区大小,您可以控制声音对变化的fr值的响应程度。

你的问题是未定义的fr是由于你的回调是一个直接的c函数。您的fr变量被声明为objective-c实例变量,作为Singer对象的一部分。默认情况下无法访问它们。

看看这个项目,看看他如何在回调中实现对实例变量的访问。基本上,他将对其实例的引用传递给回调函数,然后通过它访问实例变量。

https://github.com/youpy/dowoscillator

通知:

Sinewave *sineObject = inRefCon;
float freq = sineObject.frequency * 2 * M_PI / samplingRate;

AURenderCallbackStruct input;
input.inputProc = RenderCallback;
input.inputProcRefCon = self;

此外,您需要将回调函数移到@implementation块之外,因为它实际上并不是您的Singer对象的一部分。

您可以在此处看到这一切:https://github.com/coryalder/SineWaver

相关问题