我使用mpg123和out123在C ++中创建了非常简单的mp3播放器,遵循本教程: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改为非常大的数字并没有帮助,所以问题不存在。令人惊讶的是,当我将一些东西打印到控制台时,它似乎工作得更顺畅。但问题并没有消失。
我的猜测是某些东西没有同步,但这就是我能说的全部......我的程序在播放每一块声音后是否应该在循环中睡觉?好吧,我试图在几乎所有地方放置一个睡眠命令,但它没有取得多大成就。肯定有一些我做错了但我无法想象出来。所以我的问题是:每次启动新文件时,如何阻止我的播放器播放这种可怕的声音?