Помогите с живым обновлением звука на iPhone - PullRequest
0 голосов
/ 28 ноября 2010

Мой вопрос немного сложен, и я не совсем опытный (я мог бы неправильно понять некоторые термины), так что здесь. Я объявляю экземпляр объекта под названием «Певица». Экземпляр называется "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». Бьюсь об заклад, это потому, что по какой-то причине он не видит мое предыдущее объявление в заголовочном файле (как float). Однако, опять же, если я пропущу эту строку, код не будет компилироваться, потому что "fr1 is undeclared". Б) То, что я изменил значение fr1, не означает, что singer1 обновит значение, хранящееся в переменной «Playcallback» или что-либо еще, отвечающее за обновление выходных буферов. Возможно, это можно исправить кодировкой по-другому? C) даже если это сработало, при паузе / воспроизведении звука все еще есть заметный «пробел», который мне нужно устранить. Это может означать полный пересмотр кода, так что я могу «динамически» вставлять новые значения, ничего не нарушая. Однако причина, по которой я собираюсь опубликовать все эти усилия, заключается в том, что этот метод выполняет именно то, что я хочу (я могу вычислить значение математически, и оно попадает прямо в ЦАП, что означает, что я могу использовать его в будущем для создания треугольника , квадрат и т. д. машет легко). Я загрузил Singer.h и .m в pastebin для вашего удовольствия, возможно, они помогут. Извините, я не могу опубликовать 2 HTML-тега, поэтому вот полные ссылки. (http://pastebin.com/ewhKW2Tk) (* 1 010 *

Итак, TL; DR, все, что я действительно хочу сделать, - это уметь определять текущее уравнение / значение для 4 волн и переопределять их очень часто без паузы в звуке. Благодарю. (И извините, если сообщение сбивало с толку или сбивалось с толку, что я вполне уверен, что это произошло.)

1 Ответ

1 голос
/ 28 ноября 2010

Насколько я понимаю, ваша функция обратного вызова вызывается каждый раз, когда требуется перезаполнение буфера. Таким образом, изменение fr1..fr4 изменит форму волны, но только при обновлении буфера. Вам не нужно останавливать и перезапускать звук, чтобы получить изменение, но вы заметите резкий сдвиг тембра, если вы измените свои значения fr. Для того, чтобы получить плавный переход по тембру, вам нужно реализовать что-то, что плавно изменяет значения fr с течением времени. Изменение размера буфера даст вам некоторый контроль над тем, насколько звук реагирует на изменение значений fr.

Ваша проблема с неопределенностью fr связана с тем, что обратный вызов является прямой функцией c. Ваши переменные fr объявлены как переменные экземпляра target-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

...