
Сообщение от
psb
в регуляторе чистая математика. где не понятно?
Набросал на си твою програму, как я ее понял:
Код:
// 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;
}
На 882 выходит только через несколько сот итераций.
А колебания длины кадра даже на 1000-й итерации доходят до 0.1, что очень грубо.
Пока что не вникал в подробности, только перенес на Си.