Создание системы DSP с нуля
Мне нравится электронная музыка, и меня интересует, как все это клеится.
Я нашел много полезных вопросов о переполнении стека в библиотеках, которые можно использовать для воспроизведения аудио, фильтров и т.д. Но мне действительно интересно, что на самом деле происходит: как передаются данные между эффектами и осцилляторами? Я провел исследование математической стороны dsp, и у меня есть эта проблема, но я не уверен в том, какую систему буферизации использовать и т.д. Конечная цель состоит в том, чтобы иметь простой объект иерархии эффектов и осцилляторов, которые передают данные между собой (возможно, используя многопоточность, если я не выдержу все мои волосы, пытаясь их реализовать). Это не будет следующей причиной Propellerhead, но меня интересует, как все это работает, и это больше упражнение, чем что-то, что будет готовить конечный продукт.
В настоящий момент я использую .net и С#, и недавно я узнал F # (что может или не может привести к каким-то интересным способам обработки данных), но если они не подходят для задания, я могу при необходимости изучить другую систему,
Вопрос: какой лучший способ получить большие объемы данных сигнала через программу, используя буферы? Например, было бы лучше использовать Queue, Array, Linked List и т.д.? Должен ли я сделать образцы неизменяемыми и создавать новый набор данных каждый раз, когда я применяю эффект к системе или просто редактирую значения в буфере? Shoud У меня есть объект стиля диспетчера/потока пула, который организует передачу данных или функции эффектов передают данные непосредственно между собой?
Спасибо.
EDIT: другой связанный с этим вопрос заключается в том, как я мог бы использовать API окон для воспроизведения этого массива? Я действительно не хочу использовать DirectShow, потому что Microsoft в значительной степени оставила его умирать сейчас
EDIT2: спасибо за все ответы. Посмотрев на все технологии, я буду использовать XNA 4 (я потратил некоторое время на трафик в Интернете и нашел этот сайт, который объясняет, как это сделать) или NAudio для вывода музыка... не уверен, какой еще, зависит от того, насколько продвинута система. Когда выйдет С# 5.0, я буду использовать его асинхронные возможности для создания архитектуры эффектов поверх этого. Я в значительной степени использовал всех одинаково, так что теперь у меня есть головоломка о том, кому дать награду...
Ответы
Ответ 1
Вы посмотрели VST.NET(http://vstnet.codeplex.com/)? Это библиотека для записи VST с использованием С#, и в ней есть несколько примеров. Вы также можете рассмотреть возможность написания VST, чтобы ваш код можно было использовать из любого хост-приложения (но даже если вы этого не хотите, поиск кода может быть полезным).
Сигнальные данные обычно большие и требуют большой обработки. Не используйте связанный список! Большинство библиотек, которые я знаю, просто используют массив для размещения всех аудиоданных (в конце концов, что ожидает звуковая карта).
Из примера VST.NET:
public override void Process(VstAudioBuffer[] inChannels, VstAudioBuffer[] outChannels)
{
VstAudioBuffer audioChannel = outChannels[0];
for (int n = 0; n < audioChannel.SampleCount; n++)
{
audioChannel[n] = Delay.ProcessSample(inChannels[0][n]);
}
}
Аудиоканал - это оболочка вокруг неуправляемого буфера с плавающей запятой.
Вероятно, вы сохраните свои образцы в неизменяемом массиве. Затем, когда вы хотите воспроизвести их, вы скопируете данные в выходной буфер (измените частоту, если хотите) и выполните эффекты в этом буфере. Обратите внимание, что вы можете использовать несколько выходных буферов (или каналов) и суммировать их в конце.
Edit
Я знаю два низкоуровневых способа играть в ваш массив: DirectSound и WaveOut из Windows API. С# Пример использования DirectSound. Пример С# с WaveOut. Однако вы можете использовать внешнюю библиотеку более высокого уровня, например NAudio. NAudio удобна для обработки звука в формате HTML - см. Это сообщение в блоге для отправки синусоидальной волны на звуковую карту. Вы можете видеть, что они также используют массив float, который я рекомендую (если вы выполняете вычисления с использованием байтов, вы получите много алиасинга в звуке).
Ответ 2
F #, вероятно, является хорошим выбором здесь, так как он хорошо подходит для управления функциями. Функции, вероятно, являются хорошими строительными блоками для создания и обработки сигналов.
F # также хорошо манипулирует коллекциями вообще и массивами, в частности, благодаря функциям более высокого порядка в модуле Array.
Эти качества делают F # популярным в финансовом секторе и также полезны для обработки сигналов, я бы предположил.
Visual F # 2010 для технических вычислений содержит раздел, посвященный преобразованию Фурье, который может иметь отношение к тому, что вы хотите сделать. Я предполагаю, что есть много свободной информации об трансформации в сети, однако.
Наконец, чтобы воспроизвести образцы, вы можете использовать XNA. Я думаю, что последняя версия API (4.0) также позволяет записывать, но я никогда не использовал это. Существует известное приложение для редактирования музыки для Xbox, называемое ezmuse + Hamst3r Edition, которое использует XNA, поэтому это определенно возможно.
Ответ 3
Что касается буферизации и асинхронности/потоков/проблем синхронизации, я предлагаю вам взглянуть на новую библиотеку потоков данных TPL. С его блок-примитивами, параллельными структурами данных, сетями потоков данных, обработкой асинхронных сообщений и абстракцией на основе задач TPL (которые могут использоваться с функциями async/await С# 5), это очень подходит для приложений такого типа.
Ответ 4
Я не знаю, действительно ли это то, что вы ищете, но это был один из моих личных проектов в колледже. Я действительно не понял, как работает звук и DSP, пока я сам его не реализовал. Я пытался как можно ближе подойти к динамику, поэтому я сделал это, используя только libsndfile, для обработки тонкостей файлов для меня.
В основном, мой первый проект состоял в том, чтобы создать большой массив удвоений, заполнить его синусоидой, затем использовать sf_writef_double(), чтобы записать этот массив в файл, чтобы создать что-то, что я мог бы сыграть, и увидеть результат в редактор формы волны.
Затем я добавил еще одну функцию между вызовом синуса и вызовом записи, чтобы добавить эффект.
Таким образом вы начинаете играть с очень низкоуровневыми осцилляторами и эффектами, и вы можете сразу увидеть результаты. Кроме того, это очень маленький код, чтобы получить что-то вроде этого.
Лично я начну с самого простого возможного решения, которое вы можете, затем медленно добавьте. Попробуйте просто записать файл и использовать аудиоплеер для его воспроизведения, поэтому вам не нужно разбираться с аудио-авизой. Просто используйте один массив для запуска и изменения на месте. Определенно начинайте однопоточность. По мере роста вашего проекта вы можете перейти к другим решениям, таким как трубы вместо массива, многопоточность или работу с аудио API.
Если вы хотите создать проект, который вы можете отправить, в зависимости от того, что это такое, вам, вероятно, придется перейти к более сложным библиотекам, например, к обработке аудио в реальном времени. Но основы, которые вы узнаете, делая простой способ выше, определенно помогут, когда вы доберетесь до этого момента.
Удачи!
Ответ 5
Я сделал довольно много DSP в реальном времени, хотя и не со звуком. Хотя любой из ваших идей (неизменяемый буфер) vs (изменяемый модифицированный буфер) может работать, я предпочитаю создавать один постоянный буфер для каждой ссылки в сигнальном тракте. Большинство эффектов не поддаются изменению, поскольку каждый входной образец влияет на несколько выходных выборок. Метод буфера для каждой ссылки работает особенно хорошо, когда у вас есть этапы повторной дискретизации.
Здесь, когда образцы приходят, первый буфер перезаписывается. Затем первый фильтр считывает новые данные из своего входного буфера (первый буфер) и записывает на его вывод (второй буфер). Затем он вызывает второй этап для чтения из второго буфера и записи в третий.
Этот шаблон полностью исключает динамическое распределение, позволяет каждому этапу сохранять переменное количество истории (поскольку эффекты нуждаются в некоторой памяти) и очень гибко, поскольку позволяет перегруппировать фильтры в пути.
Ответ 6
Хорошо, у меня тоже будет удар по щедрости:)
Я нахожусь в очень похожей ситуации. Я занимаюсь электронной музыкой целую вечность, но только за последние пару лет я начал изучать фактическую обработку звука.
Вы упомянули, что вы изучили математику. Я думаю, что это важно. В настоящее время я пробиваю себе путь через Ken Steiglitz 'A Digital Signal Processing Primer - с приложениями для цифрового аудио и компьютерной музыки. Если вы не знаете своих сложных чисел и фазоров, это будет очень сложно.
Я парень Linux, поэтому начал писать LADSPA-плагины на C. Я думаю, что хорошо начать с этого базового уровня, чтобы действительно понять, что происходит. Если бы я был в Windows, я бы загрузил VST SDK из Steinberg и написал бы быстрое доказательство плагина концепции, которое просто добавляет шум или что-то еще.
Еще одно преимущество выбора структуры, такой как VST или LADSPA, заключается в том, что вы можете сразу использовать свои плагины в своем обычном аудио-пакете. Удовлетворение применения вашего первого встроенного плагина к звуковой дорожке является непревзойденным. Кроме того, вы сможете делиться своими плагинами с другими музыкантами.
Вероятно, есть способы сделать это в С#/F #, но я бы порекомендовал С++, если вы планируете писать плагины VST, чтобы избежать лишних накладных расходов. Это похоже на отраслевой стандарт.
В терминах буферизации я использую круговые буферы (хорошая статья здесь: http://www.dspguide.com/ch28/2.htm). Хорошее упражнение состоит в том, чтобы реализовать фильтр с конечным ответом (что Steiglitz называется фильтром прямого доступа) - они полагаются на буферизацию и довольно забавны для игры.
У меня есть репо на Github с несколькими очень базовыми плагинами LADSPA. Архитектурные различия в стороне, они потенциально могут быть полезны для тех, кто пишет плагины VST. https://github.com/andreasjansson/my_ladspa_plugins
Другим хорошим источником кода примера является проект CSound. Там есть тонны кода DSP, и программное обеспечение ориентировано прежде всего на музыкантов.
Ответ 7
Начните с чтения этого и этого.
Это даст вам представление о том, что вы должны делать.
Затем изучите архитектуру DirectShow и узнайте, КАК не делать этого, но попытайтесь создать свою упрощенную версию.
Ответ 8
Вы можете посмотреть BYOND. Это среда для программного аудио /midi инструмента и создания эффекта в С#. Он доступен как автономный, так и как инструмент и эффект VST.
ПОЛНОЕ РАСКРЫТИЕ Я разработчик BYOND.