iphone - 帮助在iPhone上实时更新声音

标签 iphone objective-c audio ios4 audiounit

我的问题有点棘手,而且我经验不足(我可能会误解一些术语),所以请继续。
我正在声明一个名为“Singer”的对象的实例。该实例称为“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个波形的当前等式/值,并经常重新定义它们,而不会出现声音上的缝隙。
谢谢。 (并且很抱歉,如果帖子令人困惑或偏离正轨,我很确定是这样的。)

最佳答案

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

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

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

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

关于iphone - 帮助在iPhone上实时更新声音,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4294428/

相关文章:

iOS:当前AVAudioPlayer的AudioUnit

java - 如何用 C/C++ 或 Java 生成真正的贝斯吉他声音?

c# - UWP AudioGraph 设置不适用于所有设备,HRESULT : 0x88960001 thrown on AddOutgoingConnection

iphone - 使用来自 Apple 示例的 Mailcomposer 的代码时出错

iphone - WIF 是保护 iPhone 的 WCF 4.0 Restful 服务的好选择吗

iphone - Objective-C,使用 UI 事件取消调度队列

ios - 减少启动图像时间 IOS

iphone - Frenzapp如何获取其他应用程序的版本?

iphone - iOS:使用父类(super class)的 getter 和 setter 的属性不再适用于 Xcode 4.4

javascript - 如何在浏览页面时保持音频播放?