потоковая передача — DirectSoundBuffer прекращает воспроизведение в определенном месте — без уведомлений

Я использую DirectSoundBuffer DirectSound для воспроизведения голосовых данных, которые я передаю по сети. Природа голоса / речи заключается в том, что они не обязательно постоянно передаются (запускаются и останавливаются), а также могут иметь различный размер пакета (что затрудняет прогнозирование места остановки буфера). Я держу StoppingPoint переменная, которая отслеживает, где в моем буфере я записал (это также учитывает циклический характер этого буфера). Если StoppingPoint достигнут, я хотел бы остановить воспроизведение моего буфера. Также я StoppingPoint также означало бы момент, с которого я также хотел бы начать писать.

My buffer
|==============================|--------------------------|
^                        ^             ^
|                        |             |
Voice Data            Stopping point   Old/Garbage
data

Кроме того, я не могу использовать уведомления, потому что для использования уведомления буфер должен быть остановлен. Но в моем случае вполне вероятно, что во время воспроизведения буфера будет поступать больше данных, таким образом отталкивая мое значение «StoppingPoint».

Сейчас у меня есть функция, которая называется каждый кадр. Эта функция, помимо прочего, проверяет, где находится курсор воспроизведения. Если курсор воспроизведения пройден, StoppingPoint местоположение, он останавливает буфер и перемещает курсор воспроизведения обратно в StoppingPoint место нахождения. Пока это работает нормально, но, как и следовало ожидать, курсор Play довольно часто выходит за StoppingPoint, Это означает, что немного старых / мусорных данных воспроизводится каждый раз, когда достигается конец потоковых данных.

Мне просто любопытно, есть ли способ остановить воспроизведение DirectSoundBuffer с определенным смещением? Я хотел бы записать данные в буфер, затем воспроизвести, а затем остановить его точно в месте, описанном моим StoppingPoint переменная без превышения.

Примечание: я не включил никакого кода, потому что это скорее решение высокого уровня, в котором я нуждаюсь. Моя реализация невероятно прямолинейна, типична и по большей части работает. Мне просто нужно подтолкнуть в правильном направлении, чтобы снять перекос моего StoppingPoint, Возможно, есть функция, которую я могу использовать? Или какой-то другой алгоритм, который обычно используется для достижения этой цели?

2

Решение

Я придумала решение, но мне все еще интересны любые отзывы или альтернативные решения. Я не уверен, что способ, которым я это сделал, в порядке, но, похоже, он дает желаемые результаты. Хотя мое решение кажется слишком запутанным …

1) Всякий раз, когда я пишу данные, я пишу в буфере Write Cursor или StoppingPoint — что будет позже. Это делается для того, чтобы не останавливаться, а затем записывать в том «неприкасаемом» пространстве между курсором воспроизведения и курсором записи, данные которого уже были выделены для воспроизведения.

DWORD writeCursorOffset = 0;
buffer->GetCurrentPosition(NULL, &writeCursorOffset);

//if write cursor has passed stopping point, then we need to write from there.
//So update m_StoppingPoint to reflect the new writing position.
m_StoppingPoint = m_StoppingPoint > writeCursorOffset ? m_StoppingPoint : writeCursorOffset;

2) Я добавил тишину после каждой записи, но оставил StoppingPoint указать в конце реальных голосовых данных. Например.

|==============================|*********|---------------------|
^                         ^      ^              ^
|                         |      |              |
Voice data                  Stopping  Silence    Old/Garbage
Point                  Data

3) Если буфер Play Cursor прошел StoppingPointЯ бы тогда перестал проигрывать буфер. Даже если Play Cursor выходит за рамки, все, что он будет играть, это тишина.

//error checking removed for demonstration purposes
buffer->Stop();

4) Сразу после остановки я бы обновил StoppingPoint быть равным концу тишины. Это гарантирует, что когда поступит больше речевых данных, буфер сначала не будет воспроизводить паузу.

//don't forget that modulo at the end - circular buffer!
m_StoppingPoint = (m_StoppingPoint + SILENCE_BUFFER_SIZE) % BufferSize;

|==============================|*********|-------------------|
^
|
Move Stopping
Point here

Опять же, если я сделал что-то явно злое, пожалуйста, дайте мне знать!

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]