Одновременно генерировать несколько синусоидальных волн в буфер сэмплов для аудиоустройства (iOS) - PullRequest
2 голосов
/ 21 июля 2011

Учитывая массив (изменяющейся длины) частот и амплитуд, могу ли я сгенерировать один аудио буфер на основе выборки, включающий все тоны в массиве? Если нет, то как лучше всего создать несколько тонов в одном аудиоустройстве? Пусть каждая нота генерирует свой собственный буфер, а затем суммирует их в выходной буфер? Разве это не то же самое, что делать все сразу?

Работа над приложением для iOS, которое генерирует заметки от прикосновений, учитывая использование STK, но не желая отправлять сообщения с заметками, скорее всего будет генерировать синусоидальные тоны для заметок, которые я держу в массиве. Каждая нота фактически должна произвести две синусоиды, с различной частотой и амплитудой. Одна нота может воспроизводить ту же частоту, что и другая нота, поэтому сообщение об отключении ноты на этой частоте может вызвать проблемы. В конце концов я хочу управлять амплитудными (adsr) конвертами для каждой ноты вне аудиоустройства. Я также хочу, чтобы время отклика было как можно более быстрым, поэтому я хочу проделать дополнительную работу / обучение, чтобы сохранить уровень звука на минимальном уровне.

Я работал с примерами синусоидального генератора. Попробовал по существу удвоить один из них, что-то вроде:

Buffer [frame] = (sin (theta1) + sin (theta2)) / 2

Увеличивая theta1 / theta2 на частоту 1 / частоту 2 по сравнению с частотой дискретизации (я понимаю, что это не самый эффективный вызов sin ()), но получаю эффекты сглаживания. Я еще не нашел пример с несколькими частотами или источниками данных, кроме чтения аудио из файла.

Есть предложения / примеры? Изначально каждая нота генерировала свой собственный аудиоустройство, но это дало мне слишком большую задержку от прикосновения к звучанию ноты (и, кажется, тоже неэффективно). Я новичок в этом уровне программирования, чем цифровой звук в целом, поэтому, пожалуйста, будьте осторожны, если я упускаю что-то очевидное.

1 Ответ

2 голосов
/ 27 июля 2011

да, конечно, вы можете, вы можете делать все что угодно внутри вашего обратного вызова рендеринга. когда вы устанавливаете этот вызов обратно, вы можете передать указатель на объект.

этот объект может содержать состояния включения / выключения для каждого тона. фактически объект может содержать метод, отвечающий за заполнение буфера. (просто убедитесь, что объект неатомный, если это свойство - в противном случае вы получите артефакты из-за проблем с блокировкой)

Чего именно вы пытаетесь достичь? Вам действительно нужно генерировать на лету?

в этом случае вы рискуете перегрузить функцию обратного вызова рендеринга аудиоустройства remoteIO, что приведет к сбоям и артефактам

вы можете избежать неприятностей с симулятором, а затем перенести его на устройство и обнаружить, что он таинственным образом больше не работает, потому что вы работаете на процессоре, в 50 раз меньшем, и один обратный вызов не может завершиться до следующего приходит

сказав, что вы можете сойти с рук много

Я сделал 12-тональный проигрыватель, который может одновременно воспроизводить любое количество отдельных тонов

все, что я делаю, - это наличие кольцевого буфера для каждого тона (я использую довольно сложный сигнал, так что это занимает много времени, фактически я вычисляю его при первом запуске приложения и затем загружаю его из файла) и поддерживать заголовок чтения и включенный флаг для каждого кольца.

Затем я добавляю все в обратный вызов рендеринга, и это прекрасно работает на устройстве, даже если все 12 играют вместе. Я знаю, что документация говорит вам не делать этого, она рекомендует использовать этот обратный вызов только для того, чтобы заполнить один буфер из другого, но вы можете многого избежать, и это PITA для кодирования какой-то системы буферизации, которая вычисляет в другой теме.

...