аудио — (C ++) Музыкальный проигрыватель играет мусор в начале

Я создал очень простой mp3-плеер на C ++, используя mpg123 и out123, следуя этому руководству: https://www.kasrajamshidi.com/blog/audio. Тем не менее, у меня была проблема, когда проигрыватель запускался: в течение первых нескольких секунд он воспроизводил шум мусора. Этот звук не был одинаковым каждый раз. Иногда это занимало больше времени, иногда это было почти не слышно.

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

Вот мой код:

#include <iostream>
#include <mpg123.h>
#include <out123.h>

// If i print messages music starts much smoother...
// (But the problem itself does not disappear).
#define PRINT_BUFFER_STATE false

// Size of the circular buffer.
const int BUFFER_SIZE = 4;

int main(int argc, char **argv)
{
// Initialize mpg123
if(mpg123_init() != MPG123_OK)
return 255;

mpg123_handle *mpg_handle = mpg123_new(nullptr, nullptr);
out123_handle *out_handle = out123_new();

// This buffer is circular. The inxed of point we write is far before
// the place we play from. bytes_written[i] tells us how many bytes
// were written to buffer[i]. This is the number of bytes we need to output,
// when we play from it.
unsigned char **buffer =
(unsigned char **)alloca(sizeof(unsigned char *) * BUFFER_SIZE);
std::size_t *bytes_written =
(std::size_t *)alloca(sizeof(std::size_t) * BUFFER_SIZE);

// These indexes tell us where we do we write bytes,
// and from where do we play them.
int play_buffer = 0;
int write_buffer = 0;

int number_of_clips = 2;
char **clip_path = (char **)alloca(sizeof(char *) * number_of_clips);
clip_path[0] = "/home/mateusz/Music/guitar.mp3";
clip_path[1] = "/home/mateusz/Music/drums.mp3";

for (int clip = 0; clip < number_of_clips; ++clip)
{
// Open a given file with mpg123 (to get format,
// which will then be passed to out device).
mpg123_open(mpg_handle, clip_path[clip]);

// Set format details:
int channels = 0;
int encoding = 0;
long rate = 0;
mpg123_getformat(mpg_handle, &rate, &channels, &encoding);

// Allocate the contets of the circulat buffer.
std::size_t buffer_size = mpg123_outblock(mpg_handle);
for (int i = 0; i < BUFFER_SIZE; ++i)
buffer[i] = (unsigned char *)malloc(sizeof(unsigned char) * buffer_size);

// Start by filling part of the bufer so that the index we write
// is ahead.
for (write_buffer = 0;
write_buffer < BUFFER_SIZE-1;
++write_buffer)
{
mpg123_read(mpg_handle, buffer[write_buffer], buffer_size,
&bytes_written[write_buffer]);

// If there is nothing to read we break the loop.
if (!bytes_written[write_buffer])
break;
}

// Set out handle to the device we'll play from with default parameters.
out123_open(out_handle, nullptr, nullptr);
out123_start(out_handle, rate, channels, encoding);

play_buffer = 0;

// play_buffer should never catch write_buffer unless
// the second one finished its job.
while (write_buffer != play_buffer)
{
#if PRINT_BUFFER_STATE
std::cout << "W: " << write_buffer << " R: " << play_buffer << "\n";
#endif
out123_play(out_handle, buffer[play_buffer],
bytes_written[play_buffer]);

mpg123_read(mpg_handle, buffer[write_buffer], buffer_size,
&bytes_written[write_buffer]);

play_buffer = (play_buffer + 1) % BUFFER_SIZE;
if (bytes_written[write_buffer])
write_buffer = (write_buffer + 1) % BUFFER_SIZE;
}

for (int i = 0; i < BUFFER_SIZE; ++i)
free(buffer[i]);

out123_stop(out_handle);
out123_close(out_handle);
mpg123_close(mpg_handle);
}

out123_del(out_handle);
mpg123_delete(mpg_handle);
mpg123_exit();

return 0;
}

Изменение BUFFER_SIZE на действительно большое число не помогает, поэтому проблема не в этом. Удивительно, но когда я печатаю что-то на консоли, кажется, что это работает намного плавнее. Но проблема не исчезает.

Я предполагаю, что что-то не синхронизировано, но это действительно все, что я могу сказать … Должна ли моя программа спать в цикле после воспроизведения каждого куска звука? Ну, я пытался поставить команду сна почти везде, но она не достигла многого. Должно быть, я что-то не так делаю, но не могу понять. Итак, мой вопрос: как я могу запретить проигрывателю проигрывать этот ужасный звук каждый раз, когда он запускает новый файл?

0

Решение

Задача ещё не решена.

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

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

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