скрин
скрин
Последний раз редактировалось ZEK; 22.02.2014 в 20:02.
В данном случае работает потому, что 'случайно' параметры кратны друг другу.
при 50Гц 48000/50 = 960 (а это 480*2),
ну и при 100Гц 48000/100 = 480.
Т.е. все кратно дискретности буфера на Win7.
---------- Post added at 03:24 ---------- Previous post was at 02:25 ----------
Попробовал понять, все-таки ничего не понял)
Попробуй изобразить на си, если не сложно.
блин, ну я же уже и словами описывал... что именно там не понятно? функции (def) должны быть понятны.
# filter 1
fff.append(t2-t1)
fff=fff[-200:]
avg=float(sum(fff))/len(fff)
fff - массив из чисел. append добавляет в него новое число, fff=fff[-200:] оставляет последние 200 чисел, avg - сумма всех чисел делится на кол-во чисел. второй фильтр - то же самое.
в регуляторе чистая математика. где не понятно?
Набросал на си твою програму, как я ее понял:
На 882 выходит только через несколько сот итераций.Код:// PSB-Test.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include "math.h" #define min(a, b) (((a) < (b)) ? (a) : (b)) #define max(a, b) (((a) > (b)) ? (a) : (b)) #define DIMLEN 200 float QUANT = 882; // рассчетное число сэмплов в прерывание float RES = 480; // разрешение указателей звукового буфера float bufpos = 0; // позиция буфера записи float playpos = 0; // позиция буфера чтения float FFF[DIMLEN]; // фильтр 1 float FFF2[DIMLEN]; // фильтр 2 float delta = 0; // добавка к рассчетному числу сэмплов float I = 0; // сост. интегратора float avg = 0; // среднее зн. числа сэмплов long len = 1; // начальная длина массива void render_frame(float n) // put data to buffer { bufpos = bufpos + long(n + 0.5); } void play_frame(float n) { n = n - 5 + rand() * 10.0 / RAND_MAX; // add some noise to samples number playpos = playpos + n; if (bufpos < playpos) printf("Underrun!\n"); } float get_pos(void) // get rounded position { return((long)((long)playpos / RES) * RES); } float lim(float v, float l, float h) // limit value from l to h { return(min(h, max(l, v))); } int _tmain(int argc, _TCHAR* argv[]) { long j, k; float t1, t2, sum, err, P, smps; printf("Test!\n"); render_frame(RES); // пребуфферинг for (j=0; j<1050; j++) // заполняем" буфер, проигрыванием, вычисляем изменение указателя { t1 = get_pos(); // render_frame(QUANT + delta); // play_frame(QUANT); // t2 = get_pos(); // printf("avg = %f, b-p = %f, delta = %f, I = %f\n", avg, bufpos-playpos, delta, I); // filter 1 for (k=0; k<(DIMLEN-1); k++) // FFF[k] = FFF[k+1]; // FFF[k] = t2 - t1; // sum = 0; // for (k=DIMLEN-len; k<DIMLEN; k++) // sum = sum + FFF[k]; // avg = sum / len; // // filter 2 for (k=0; k<(DIMLEN-1); k++) // FFF2[k] = FFF2[k+1]; // FFF2[k] = avg; // sum = 0; // for (k=DIMLEN-len; k<DIMLEN; k++) // sum = sum + FFF2[k]; // avg = sum / len; // вычисленное реальное число сэмплов за фрейм // ПИ-регулятор if (len == 200) // работает, если есть статистика по 200 фреймам { smps = long(QUANT + delta + 0.5); // кол-во положенных сэмплов (то, что ушло в render_frame() в этот раз) err = lim(avg - smps, -5, 5); // разница между вычисленным средним и отправленным I = I + err * 0.01; // ограниченный интегратор I = lim(I, -5, 5); // P = 0.5 * err; // проп. звено delta = P + I; // сумма } else len++; } return 0; }
А колебания длины кадра даже на 1000-й итерации доходят до 0.1, что очень грубо.
Пока что не вникал в подробности, только перенес на Си.
да, 0.1 семпла.
В реальных условиях, если я не ошибаюсь, около 0.01. Причем никаких заметных на слух колебаний даже в самом начале регулировки. Таким образом сразу после запуска эмулятора слышится ровный, никуда не плавающий звук.
И еще, ты не знаешь о таком моменте, что нет никакой гарантии точного временнОго детектирования начала кадра. Т.е. в среднем, колебания может быть в несколько сканлайнов, но, особенно в зависимости от загрузки винды, скачки могут быть непредсказуемые и достаточно большие. У меня на это тоже идет корректировка, без чего не было бы такой точности.
+- даже несколько целых сэмплов за фрейм ты не услышишь.
Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)