Преобразование данных, записанных звуковой картой, в mp3 с использованием libmp3lame - PullRequest
0 голосов
/ 05 марта 2019

Я написал следующий код для преобразования данных, захваченных звуковой картой (через устройство монитора pulseaudio) в mp3:

if (!current_song_)
{
    transcode_start_evt_.set();
    return;
}
is_working_ = true;
transcode_start_evt_.set();

current_song_->sink_->remove_silent_frames(250);

std::string filename = "/home/nidhoegger/" + current_song_->song->get_artist_string() + " - " + current_song_->song->get_name() + ".mp3";

FILE *mp3_file = ::fopen(filename.c_str(), "wb");

if (!mp3_file)
{
    logger_.error("Could not open %s for writing.", filename.c_str());
    return;
}

size_t frames_avail = current_song_->sink_->frames_available();
size_t frames_done = 0;

lame_t lame = ::lame_init();

::lame_set_in_samplerate(lame, 44100);
::lame_set_num_channels(lame, 2);
::lame_set_brate(lame, 192);
::lame_set_quality(lame, 2);
::lame_set_VBR(lame, vbr_off);
::lame_init_params(lame);

/*::id3tag_init(lame);
::id3tag_add_v2(lame);
::id3tag_set_title(lame, current_song_->song->get_name().c_str());
::id3tag_set_artist(lame, current_song_->song->get_artist_string().c_str());
::id3tag_set_album(lame, current_song_->song->get_album_name().c_str());
// TODO: Year, Genre, Album Art, etc*/


size_t frames_per_step = 44100;
size_t data_size = frames_per_step * current_song_->sink_->get_frame_size();
short *data = (short *)::malloc(data_size);

int worst_case_mp3_size = 2 * frames_per_step + 7200;
unsigned char *mp3_data = (unsigned char *)::malloc(worst_case_mp3_size);

bool finished = false;

while (!finished && !canceled_)
{
    size_t frames_read = current_song_->sink_->get_frames(frames_per_step, data, data_size);
    int mp3_data_written = 0;
    if (frames_read > 0)
    {
        if ((mp3_data_written = ::lame_encode_buffer_interleaved(lame, data, (int)frames_read, mp3_data, worst_case_mp3_size)) < 0)
        {
            logger_.error("Error encoding mp3 (%d)", mp3_data_written);
            cb(current_song_->song->get_uri(), false);
            current_song_ = sprotzify::song_info_ptr_t();
            return;
        }
        frames_done += frames_read;

        controller_->transcode_set_progress(current_song_->song->get_uri(), (float)frames_done / (float)frames_avail);
    }
    else
    {
        ::lame_encode_flush(lame, mp3_data, worst_case_mp3_size);
        finished = true;
    }

    size_t written = ::fwrite(mp3_data, 1, (size_t)mp3_data_written, mp3_file);
    if (written != mp3_data_written)
    {
        logger_.error("Could not write data");
        cb(current_song_->song->get_uri(), false);
        current_song_ = sprotzify::song_info_ptr_t();
        return;
    }
}

::fclose(mp3_file);

::free(data);
::free(mp3_data);

::lame_close(lame);

Выходной файл mp3 можно воспроизводить очень хорошо, и он содержит все аудиоданные.Проблема в том, что аудиоплееры на моем компьютере будут показывать неверную длину трека.Есть ли какой-то вызов libmp3lame Я не могу правильно завершить файл?К сожалению, я не нахожу много информации об API libmp3lame.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...