|
|
|
/***************************************************************************
|
|
|
|
encoder_mp3.cpp
|
|
|
|
-------------------
|
|
|
|
begin : Sat Aug 20 2005
|
|
|
|
copyright : (C) 2005 by Martin Witte
|
|
|
|
email : witte@kawo1.rwth-aachen.de
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
* *
|
|
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
|
|
* it under the terms of the GNU General Public License as published by *
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
|
|
* (at your option) any later version. *
|
|
|
|
* *
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
#include "encoder_mp3.h"
|
|
|
|
|
|
|
|
#include <tqmutex.h>
|
|
|
|
#include <tdelocale.h>
|
|
|
|
|
|
|
|
RecordingEncodingMP3::RecordingEncodingMP3(TQObject *parent, SoundStreamID ssid,
|
|
|
|
const RecordingConfig &cfg, const RadioStation *rs,
|
|
|
|
const TQString &filename)
|
|
|
|
: RecordingEncoding(parent, ssid, cfg, rs, filename)
|
|
|
|
#ifdef HAVE_LAME
|
|
|
|
,
|
|
|
|
m_MP3Buffer(NULL),
|
|
|
|
m_MP3BufferSize(0),
|
|
|
|
m_MP3Output(NULL),
|
|
|
|
m_ID3Tags(NULL),
|
|
|
|
m_LAMEFlags(NULL),
|
|
|
|
m_MP3LBuffer(NULL),
|
|
|
|
m_MP3RBuffer(NULL)
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
m_config.m_OutputFormat = RecordingConfig::outputMP3;
|
|
|
|
m_config.m_SoundFormat.m_Encoding = "mp3";
|
|
|
|
openOutput(filename);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
RecordingEncodingMP3::~RecordingEncodingMP3()
|
|
|
|
{
|
|
|
|
closeOutput();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static TQMutex lameSerialization;
|
|
|
|
|
|
|
|
void RecordingEncodingMP3::encode(const char *_buffer, size_t buffer_size, char *&export_buffer, size_t &export_buffer_size)
|
|
|
|
{
|
|
|
|
if (m_error)
|
|
|
|
return;
|
|
|
|
|
|
|
|
#ifdef HAVE_LAME
|
|
|
|
short int *buffer = (short int*)_buffer;
|
|
|
|
size_t j = 0,
|
|
|
|
j_inc = (m_config.m_SoundFormat.m_Channels == 1) ? 1 : 2,
|
|
|
|
dj = (m_config.m_SoundFormat.m_Channels == 1) ? 0 : 1,
|
|
|
|
samples = buffer_size / m_config.m_SoundFormat.frameSize();
|
|
|
|
|
|
|
|
for (size_t i = 0; i < samples; ++i, j+=j_inc) {
|
|
|
|
m_MP3LBuffer[i] = buffer[j];
|
|
|
|
m_MP3RBuffer[i] = buffer[j+dj];
|
|
|
|
}
|
|
|
|
|
|
|
|
int n = 0;
|
|
|
|
lameSerialization.lock();
|
|
|
|
n = lame_encode_buffer(m_LAMEFlags,
|
|
|
|
m_MP3LBuffer,
|
|
|
|
m_MP3RBuffer,
|
|
|
|
samples,
|
|
|
|
m_MP3Buffer,
|
|
|
|
m_MP3BufferSize);
|
|
|
|
lameSerialization.unlock();
|
|
|
|
if (n < 0) {
|
|
|
|
m_errorString += i18n("Error %1 while encoding mp3. ").arg(TQString().setNum(n));
|
|
|
|
m_error = true;
|
|
|
|
} else if (n > 0) {
|
|
|
|
m_encodedSize += n;
|
|
|
|
|
|
|
|
export_buffer = (char*)m_MP3Buffer;
|
|
|
|
export_buffer_size = n;
|
|
|
|
int r = fwrite(m_MP3Buffer, 1, n, m_MP3Output);
|
|
|
|
|
|
|
|
if (r <= 0) {
|
|
|
|
m_errorString += i18n("Error %1 writing output. ").arg(TQString().setNum(r));
|
|
|
|
m_error = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool RecordingEncodingMP3::openOutput(const TQString &output)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_LAME
|
|
|
|
// m_output = NULL;
|
|
|
|
m_LAMEFlags = lame_init();
|
|
|
|
|
|
|
|
if (!m_LAMEFlags) {
|
|
|
|
m_error = true;
|
|
|
|
m_errorString += i18n("Cannot initialize lalibmp3lame. ");
|
|
|
|
} else {
|
|
|
|
lame_set_in_samplerate(m_LAMEFlags, m_config.m_SoundFormat.m_SampleRate);
|
|
|
|
lame_set_num_channels(m_LAMEFlags, 2);
|
|
|
|
//lame_set_quality(m_LAMEFlags, m_config.mp3Quality);
|
|
|
|
|
|
|
|
lame_set_mode(m_LAMEFlags, m_config.m_SoundFormat.m_Channels == 1 ? MONO : JOINT_STEREO);
|
|
|
|
|
|
|
|
// lame_seterrorf(m_LAMEFlags, ...);
|
|
|
|
// lame_setdebugf(m_LAMEFlags, ...);
|
|
|
|
// lame_setmsgf(m_LAMEFlags, ...);
|
|
|
|
|
|
|
|
lame_set_VBR(m_LAMEFlags, vbr_default);
|
|
|
|
lame_set_VBR_q(m_LAMEFlags, m_config.m_mp3Quality);
|
|
|
|
|
|
|
|
if (lame_init_params(m_LAMEFlags) < 0) {
|
|
|
|
m_error = true;
|
|
|
|
m_errorString += i18n("Cannot initialize libmp3lame parameters. ").arg(output);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!m_error) {
|
|
|
|
id3tag_init(m_LAMEFlags);
|
|
|
|
id3tag_add_v2(m_LAMEFlags);
|
|
|
|
TQString title = m_RadioStation->name() + TQString().sprintf(" - %s", (TQDateTime::currentDateTime().toString(TQt::ISODate)).ascii());
|
|
|
|
TQString comment = i18n("Recorded by TDERadio");
|
|
|
|
size_t l = title.length() + comment.length() + 10;
|
|
|
|
m_ID3Tags = new char[l];
|
|
|
|
char *ctitle = m_ID3Tags;
|
|
|
|
strcpy(ctitle, title.latin1());
|
|
|
|
char *ccomment = m_ID3Tags + strlen(ctitle) + 1;
|
|
|
|
strcpy(ccomment, comment.latin1());
|
|
|
|
id3tag_set_title(m_LAMEFlags, ctitle);
|
|
|
|
id3tag_set_comment(m_LAMEFlags, ccomment);
|
|
|
|
}
|
|
|
|
|
|
|
|
m_MP3Output = fopen(output.ascii(), "wb+");
|
|
|
|
if (!m_MP3Output) {
|
|
|
|
m_errorString += i18n("Cannot open output file %1. ").arg(output);
|
|
|
|
m_error = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t nSamples = m_config.m_EncodeBufferSize / m_config.m_SoundFormat.frameSize();
|
|
|
|
m_MP3BufferSize = nSamples + nSamples / 4 + 7200;
|
|
|
|
m_MP3Buffer = new unsigned char[m_MP3BufferSize];
|
|
|
|
|
|
|
|
m_MP3LBuffer = new short int[nSamples];
|
|
|
|
m_MP3RBuffer = new short int[nSamples];
|
|
|
|
|
|
|
|
if (!m_MP3Buffer || !m_MP3LBuffer || !m_MP3RBuffer) {
|
|
|
|
m_error = true;
|
|
|
|
m_errorString += i18n("Cannot allocate buffers for mp3 encoding. ");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_error) {
|
|
|
|
if (m_LAMEFlags) lame_close(m_LAMEFlags);
|
|
|
|
m_LAMEFlags = NULL;
|
|
|
|
if (m_MP3Output) fclose(m_MP3Output);
|
|
|
|
m_MP3Output = NULL;
|
|
|
|
if (m_MP3Buffer) delete [] m_MP3Buffer;
|
|
|
|
m_MP3Buffer = NULL;
|
|
|
|
m_MP3BufferSize = 0;
|
|
|
|
if (m_ID3Tags) delete [] m_ID3Tags;
|
|
|
|
m_ID3Tags = NULL;
|
|
|
|
if (m_MP3LBuffer) delete[] m_MP3LBuffer;
|
|
|
|
if (m_MP3RBuffer) delete[] m_MP3RBuffer;
|
|
|
|
m_MP3LBuffer = m_MP3RBuffer = NULL;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return !m_error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void RecordingEncodingMP3::closeOutput()
|
|
|
|
{
|
|
|
|
#ifdef HAVE_LAME
|
|
|
|
if (m_LAMEFlags) {
|
|
|
|
if (m_config.m_OutputFormat == RecordingConfig::outputMP3) {
|
|
|
|
int n = lame_encode_flush(m_LAMEFlags,
|
|
|
|
m_MP3Buffer,
|
|
|
|
m_MP3BufferSize);
|
|
|
|
if (n < 0) {
|
|
|
|
m_error = true;
|
|
|
|
m_errorString += i18n("Error %1 while encoding mp3. ").arg(TQString().setNum(n));
|
|
|
|
} else if (n > 0) {
|
|
|
|
int r = fwrite(m_MP3Buffer, 1, n, m_MP3Output);
|
|
|
|
if (r <= 0) {
|
|
|
|
m_error = true;
|
|
|
|
m_errorString += i18n("Error %1 writing output. ").arg(TQString().setNum(r));
|
|
|
|
} else {
|
|
|
|
lame_mp3_tags_fid(m_LAMEFlags, m_MP3Output);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (m_LAMEFlags) lame_close(m_LAMEFlags);
|
|
|
|
m_LAMEFlags = NULL;
|
|
|
|
if (m_MP3Output) fclose(m_MP3Output);
|
|
|
|
m_MP3Output = NULL;
|
|
|
|
m_MP3BufferSize = 0;
|
|
|
|
if (m_MP3Buffer) delete [] m_MP3Buffer;
|
|
|
|
m_MP3Buffer = NULL;
|
|
|
|
if (m_ID3Tags) delete [] m_ID3Tags;
|
|
|
|
m_ID3Tags = NULL;
|
|
|
|
if (m_MP3LBuffer) delete[] m_MP3LBuffer;
|
|
|
|
if (m_MP3RBuffer) delete[] m_MP3RBuffer;
|
|
|
|
m_MP3LBuffer = m_MP3RBuffer = NULL;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|