Я использую DirectSoundBuffer DirectSound для воспроизведения голосовых данных, которые я передаю по сети. Природа голоса / речи заключается в том, что они не обязательно постоянно передаются (запускаются и останавливаются), а также могут иметь различный размер пакета (что затрудняет прогнозирование места остановки буфера). Я держу StoppingPoint
переменная, которая отслеживает, где в моем буфере я записал (это также учитывает циклический характер этого буфера). Если StoppingPoint
достигнут, я хотел бы остановить воспроизведение моего буфера. Также я StoppingPoint
также означало бы момент, с которого я также хотел бы начать писать.
My buffer
|==============================|--------------------------|
^ ^ ^
| | |
Voice Data Stopping point Old/Garbage
data
Кроме того, я не могу использовать уведомления, потому что для использования уведомления буфер должен быть остановлен. Но в моем случае вполне вероятно, что во время воспроизведения буфера будет поступать больше данных, таким образом отталкивая мое значение «StoppingPoint».
Сейчас у меня есть функция, которая называется каждый кадр. Эта функция, помимо прочего, проверяет, где находится курсор воспроизведения. Если курсор воспроизведения пройден, StoppingPoint
местоположение, он останавливает буфер и перемещает курсор воспроизведения обратно в StoppingPoint
место нахождения. Пока это работает нормально, но, как и следовало ожидать, курсор Play довольно часто выходит за StoppingPoint
, Это означает, что немного старых / мусорных данных воспроизводится каждый раз, когда достигается конец потоковых данных.
Мне просто любопытно, есть ли способ остановить воспроизведение DirectSoundBuffer с определенным смещением? Я хотел бы записать данные в буфер, затем воспроизвести, а затем остановить его точно в месте, описанном моим StoppingPoint
переменная без превышения.
Примечание: я не включил никакого кода, потому что это скорее решение высокого уровня, в котором я нуждаюсь. Моя реализация невероятно прямолинейна, типична и по большей части работает. Мне просто нужно подтолкнуть в правильном направлении, чтобы снять перекос моего StoppingPoint
, Возможно, есть функция, которую я могу использовать? Или какой-то другой алгоритм, который обычно используется для достижения этой цели?
Я придумала решение, но мне все еще интересны любые отзывы или альтернативные решения. Я не уверен, что способ, которым я это сделал, в порядке, но, похоже, он дает желаемые результаты. Хотя мое решение кажется слишком запутанным …
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
Опять же, если я сделал что-то явно злое, пожалуйста, дайте мне знать!
Других решений пока нет …