Как вы переводите значение из Икс в Y плавно и со скоростью определяется другой поток.
Позвольте мне попытаться объяснить с моей конкретной проблемой, поскольку это иллюстрирует это довольно хорошо.
Я работаю над приложением для воспроизведения аудио. Когда вы резко приостанавливаете поток сэмплов в звуковом API, создавая тем самым большая разница в стоимости между последовательными выборками (т.е. изменяя синусоидальную волну на нули), вы получаете хлопающий звук.
Чтобы этого избежать, нужно плавно перевести громкость от текущего значения до нуля.
Portaudio, библиотека, которую я использую, обрабатывает аудио на фоновый поток который использует Перезвоните функционировать, когда ему нужны данные или есть данные для меня. Буфер с образцами звука и значением громкости являются аргументами для этого обратного вызова, поэтому я имею нет контроля над тем, как часто они читаются.
Как вы добиваетесь перехода громкости при следующих обстоятельствах:
Благодарю.
РЕДАКТИРОВАТЬ:
Я чувствую, что не вдавался в подробности из-за боязни переопределить проблему. Я хотел бы конкретизировать это еще немного.
В основном, поток данных может быть описан с помощью:
Loader (async producer) -> Buffer -> Player (async consumer)
Что добавляет трудности, так это то, что буфер работает как очередь (для будущей реализации очереди без блокировки и целостности данных), поэтому я не могу прикоснуться к аудиоданным, чтобы изменить их часть, чтобы они были переходными.
Это может быть недостаток дизайна, недосмотр или просто туннельное видение с моей стороны, так что это может быть изменено.
Кроме того, я хотел оставить буфер для обработки необработанных данных, поскольку объект Player отвечает за фактическое воспроизведение, и я чувствовал, что ответственность за управление громкостью.
Упрощенный обратный вызов может быть описан с помощью этого примера кода:
static int bufferCallback(const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo *timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData)
{
/* Cast data passed through stream to our structure. */
simple_player<float> *data = (simple_player<float> *)userData;
float *out = (float *)outputBuffer;
unsigned int i;
(void)inputBuffer; /* Prevent unused variable warning. */
float into;
i = 0;
unsigned int more;
while (i < framesPerBuffer)
{
more = data->buffer->get(into);
if (!more)
{
return paContinue;
}
*out = clip::soft_clip(into*data->volume);
out++;
more = data->buffer->get(into);
if (!more)
{
return paContinue;
}
*out = clip::soft_clip(into*data->volume);
out++;
i++;
}
return paContinue;
}
Замечания: При дальнейшем рассмотрении я не думаю, что смогу синхронизировать поток с потоком обработки PortAudio. Вместо этого я бы позволил самому обратному вызову изменить громкость, расширив проигрыватель и выполнив вычисления в обратном вызове, например:
static int bufferCallback(const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo *timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData)
{
/*Callback body*/
if(data->volume!=data->target_volume)
{
data->volume+=data->volume_delta;
}
return paContinue;
}
Задача ещё не решена.
Других решений пока нет …