(C ++)音乐播放器在开始播放垃圾

时间:2017-12-18 00:55:16

标签: c++ audio audio-player

我使用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改为非常大的数字并没有帮助,所以问题不存在。令人惊讶的是,当我将一些东西打印到控制台时,它似乎工作得更顺畅。但问题并没有消失。

我的猜测是某些东西没有同步,但这就是我能说的全部......我的程序在播放每一块声音后是否应该在循环中睡觉?好吧,我试图在几乎所有地方放置一个睡眠命令,但它没有取得多大成就。肯定有一些我做错了但我无法想象出来。所以我的问题是:每次启动新文件时,如何阻止我的播放器播放这种可怕的声音?

0 个答案:

没有答案