Я написал следующий код для преобразования данных, захваченных звуковой картой (через устройство монитора 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
.