Цитата Сообщение от 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, что очень грубо.
Пока что не вникал в подробности, только перенес на Си.