Tonal
> вижу у тебя в цикле преобразование дабла во флоат
И что? Это вроде быстрая операция, а изначально я использую даблы, чтобы погрешность не набегала.
gammaker
самая быстрая операция это отсутствие операции, я бы еще указатель на буфер по совметительству счетчиком цикла сделал.
А для уменьшения накладных расходов на цикл, по нескольку семплов подряд считал.
Tonal
> самая быстрая операция это отсутствие операции, я бы еще указатель на буфер по
> совметительству счетчиком цикла сделал.
Мне этот код не оптимизировать надо, а исправлять, потому что он неправильный результат даёт. Вопрос в том, как его исправить? Как обрабатывать дробные семплы?
А вот когда уже правильно заработает, тогда и буду думать о его оптимизации. И даже без оптимизации он в 6 раз быстрее, чем предыдущий вариант.
gammaker
Если на столько важно быстродействие, может стоит перейти на целочисленную арифметику? И проблем с дробными отсчётами не останется.
gammaker
>Как обрабатывать дробные семплы?
использовать фазовый аккумулятор.
Mikle
> Если на столько важно быстродействие, может стоит перейти на целочисленную
> арифметику?
А чем она быстрее? Сейчас, что дробные, что целые числа вроде одинаково работают.
Mikle
> И проблем с дробными отсчётами не останется.
А куда они денутся-то? Либо всё округлится, и они будут игнорироваться, что приведёт к искажениям, либо придётся использовать фиксированную запятую и проблема тоже останется.
Tonal
> использовать фазовый аккумулятор.
А что это? Можно пример кодом?
gammaker
в гугле забанили?
Tonal
> в гугле забанили?
Только что оттуда, ничего не ищется. Все ссылки про какие-то аналоговые устройства в основном.
gammaker
первую ссылку пробовал открывать?
Tonal
> первую ссылку пробовал открывать?
А, не, не пробовал. Сейчас открыл, вроде оно, но сейчас нет времени разбираться...
Методом размышлений, проб и ошибок пришёл к такому:
//Цикл ниже начинается от минимального значения сигнала, а нам нужно начать с нулевого, чтобы не было скачка. Сделаем половину спада перед циклом for(uint s=1; s<samplesPerDown/2; s++) inOutSamples[pos++]=( float)v, v-=dd; double fraction=fractSamplesPerDown/2; v=-volume; for( int k=0; k<fullPeriodsCount; k++) { //Нарастание for( uint s=0; s<intSamplesPerUp; s++) inOutSamples[pos++]=( float)v, v+=du; fraction+=fractSamplesPerUp; if( fraction>=1) fraction--, inOutSamples[pos++]=( float)v; v=volume; //Спад for( uint s=0; s<intSamplesPerDown; s++) inOutSamples[pos++]=( float)v, v-=dd; fraction+=fractSamplesPerDown; if( fraction>=1) fraction--, inOutSamples[pos++]=( float)v; v=-volume; }
При частоте дискретизации 11 кГц звучит похоже на мою предыдущую реализацию, но все равно звук не совсем чистый. Но повышение производительности в 7 раз с лихвой окупило переход на 48 кГц, а на такой частоте уже всё нормально. Так что принципе меня этот вариант устраивает, но если вдруг у кого появятся идеи, как сделать ещё лучше, то пишите. Естественно, этот код ещё можно будет потом оптимизировать, я ещё к этому даже не приступал.
Возможно, можно даблы заменить на float, не думаю, что там большая погрешность набежит.
Теперь наверное даже комп Тараса стриминг потянет.
Новую версию пока не закачивал, надо ещё через SSE оптимизировать, чтобы вообще летало, ну и немного пианино подправить.
А вот и новая версия: [file=97682]
Повысил частоту дискретизации с 11 кГц до 48 кГц. Звук от этого стал намного лучше. Ещё улучшил пару инструментов. Производительность упала в 4,5 раза, но после оптимизации стало ещё быстрее чем прежде! Даже в некоторых случаях превосходит самую первую версию по производительности, в которой почти не было инструментов и которая работала на частоте 11 кГц.
И это я ещё до использования SIMD так и не дошёл.
gammaker
> Вот накатал такую функцию пилообразной волны. Работает в 6 раз быстрее, но
> звучит плохо, особенно высокие частоты.
Потому что она с алиасингом!
d.m.k
> Потому что она с алиасингом!
Я так и понял. Вопрос в том, можно ли его исправить или уменьшить. Но я решил ничего не делать. Всё равно на 48 кГц не заметно.
gammaker
> Вопрос в том, можно ли его исправить или уменьшить.
Можно. Есть много способов. Самый простой (и наименее ударяющий по производительности) WT синтез, но у него свои проблемы и ограничения. Ну а дальше BLIT http://quod.lib.umich.edu/cgi/p/pod/dod-idx/alias-free-digital-sy… ms.pdf?c=icmc;idno=bbp2372.1996.101 или вообще аддитивный синтез, что на проце пока тяжеловато )
Тема в архиве.