3 Copyright (C) 2008 jlh (jlh at gmx dot ch)
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2 of the License, version 3 of
8 the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 The GNU General Public License version 2 is included with the source of
20 this program under the file name COPYING. You can also get a copy on
26 #include <lame/lame.h>
29 #include "mp3writer.h"
31 #include "preferences.h"
33 Mp3Writer::Mp3Writer() :
39 Mp3Writer::~Mp3Writer() {
41 debug("WARNING: Mp3Writer::~Mp3Writer(): File has not been closed, closing it now");
49 bool Mp3Writer::open(const QString
&fn
, long sr
, bool s
) {
50 bool b
= AudioFileWriter::open(fn
+ ".mp3", sr
, s
);
59 bitRate
= preferences
.get(Pref::OutputFormatMp3Bitrate
).toInt();
61 lame_set_in_samplerate(lame
, sampleRate
);
62 lame_set_num_channels(lame
, stereo
? 2 : 1);
63 lame_set_out_samplerate(lame
, sampleRate
);
64 // TODO: do we need this?
65 lame_set_bWriteVbrTag(lame
, 0);
66 lame_set_mode(lame
, stereo
? STEREO
: MONO
);
67 lame_set_brate(lame
, bitRate
);
68 if (lame_init_params(lame
) == -1)
74 void Mp3Writer::close() {
76 debug("WARNING: Mp3Writer::close() called, but file not open");
81 debug("WARNING: Mp3Writer::close() called but no flush happened, flushing now");
82 QByteArray dummy1
, dummy2
;
83 write(dummy1
, dummy2
, 0, true);
86 AudioFileWriter::close();
91 ID3_Frame
*getOrCreateTag(ID3_Tag
&tag
, ID3_FrameID id
) {
92 ID3_Frame
*frame
= tag
.Find(id
);
95 frame
= new ID3_Frame(id
);
96 tag
.AttachFrame(frame
);
103 void Mp3Writer::writeTags() {
107 debug("Writing tags to MP3 file");
109 QByteArray fn
= QFile::encodeName(file
.fileName());
110 ID3_Tag
tag(fn
.constData());
112 // NOTE: we don't set ID3FID_TITLE as the file name is already meant to
113 // be a good enough description of the content
115 QString str
= tagTime
.toString("yyyyddMMhhmm");
116 // TODO: the following would be better but doesn't work. find out why
117 //getOrCreateTag(tag, ID3FID_COMMENT )->GetField(ID3FN_TEXT)->Set(tagComment.utf16());
118 getOrCreateTag(tag
, ID3FID_COMMENT
)->GetField(ID3FN_TEXT
)->Set(tagComment
.toAscii().constData());
119 getOrCreateTag(tag
, ID3FID_CONTENTTYPE
)->GetField(ID3FN_TEXT
)->Set("(101)Skype Call");
120 getOrCreateTag(tag
, ID3FID_YEAR
)->GetField(ID3FN_TEXT
)->Set(str
.mid(0, 4).toAscii().constData());
121 getOrCreateTag(tag
, ID3FID_DATE
)->GetField(ID3FN_TEXT
)->Set(str
.mid(4, 4).toAscii().constData());
122 getOrCreateTag(tag
, ID3FID_TIME
)->GetField(ID3FN_TEXT
)->Set(str
.mid(8, 4).toAscii().constData());
125 mustWriteTags
= false;
128 bool Mp3Writer::write(QByteArray
&left
, QByteArray
&right
, long samples
, bool flush
) {
131 // rough upper bound formula taken from lame.h
132 long size
= samples
+ samples
/ 4 + 7200;
138 ret
= lame_encode_buffer(lame
, reinterpret_cast<const short *>(left
.constData()),
139 reinterpret_cast<const short *>(right
.constData()), samples
,
140 reinterpret_cast<unsigned char *>(output
.data()), output
.size());
142 // lame.h claims to write to the buffers, even though they're declared const, be safe
143 // TODO: this mixes both channels again! can lame take only mono samples?
144 ret
= lame_encode_buffer(lame
, reinterpret_cast<const short *>(left
.data()),
145 reinterpret_cast<const short *>(left
.data()), samples
,
146 reinterpret_cast<unsigned char *>(output
.data()), output
.size());
150 // there wasn't enough space in output
157 debug(QString("Error while writing MP3 file, code = %1").arg(ret
));
161 samplesWritten
+= samples
;
164 output
.truncate(ret
);
168 left
.remove(0, samples
* 2);
170 right
.remove(0, samples
* 2);
177 output
.resize(10240);
178 ret
= lame_encode_flush(lame
, reinterpret_cast<unsigned char *>(output
.data()), output
.size());
185 debug(QString("Error while flushing MP3 file, code = %1").arg(ret
));
190 output
.truncate(ret
);