Я создал очень простой 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 на действительно большое число не помогает, поэтому проблема не в этом. Удивительно, но когда я печатаю что-то на консоли, кажется, что это работает намного плавнее. Но проблема не исчезает.
Я предполагаю, что что-то не синхронизировано, но это действительно все, что я могу сказать … Должна ли моя программа спать в цикле после воспроизведения каждого куска звука? Ну, я пытался поставить команду сна почти везде, но она не достигла многого. Должно быть, я что-то не так делаю, но не могу понять. Итак, мой вопрос: как я могу запретить проигрывателю проигрывать этот ужасный звук каждый раз, когда он запускает новый файл?
Задача ещё не решена.
Других решений пока нет …