Update copyright notices.
[mpd-mk.git] / src / encoder / lame_encoder.c
bloba8ef7202049ba47ac79a7bedef58d509183dae7b
1 /*
2 * Copyright (C) 2003-2010 The Music Player Daemon Project
3 * http://www.musicpd.org
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "config.h"
21 #include "encoder_api.h"
22 #include "encoder_plugin.h"
23 #include "audio_format.h"
25 #include <lame/lame.h>
26 #include <assert.h>
27 #include <string.h>
29 struct lame_encoder {
30 struct encoder encoder;
32 struct audio_format audio_format;
33 float quality;
34 int bitrate;
36 lame_global_flags *gfp;
38 unsigned char buffer[32768];
39 size_t buffer_length;
42 extern const struct encoder_plugin lame_encoder_plugin;
44 static inline GQuark
45 lame_encoder_quark(void)
47 return g_quark_from_static_string("lame_encoder");
50 static bool
51 lame_encoder_configure(struct lame_encoder *encoder,
52 const struct config_param *param, GError **error)
54 const char *value;
55 char *endptr;
57 value = config_get_block_string(param, "quality", NULL);
58 if (value != NULL) {
59 /* a quality was configured (VBR) */
61 encoder->quality = g_ascii_strtod(value, &endptr);
63 if (*endptr != '\0' || encoder->quality < -1.0 ||
64 encoder->quality > 10.0) {
65 g_set_error(error, lame_encoder_quark(), 0,
66 "quality \"%s\" is not a number in the "
67 "range -1 to 10, line %i",
68 value, param->line);
69 return false;
72 if (config_get_block_string(param, "bitrate", NULL) != NULL) {
73 g_set_error(error, lame_encoder_quark(), 0,
74 "quality and bitrate are "
75 "both defined (line %i)",
76 param->line);
77 return false;
79 } else {
80 /* a bit rate was configured */
82 value = config_get_block_string(param, "bitrate", NULL);
83 if (value == NULL) {
84 g_set_error(error, lame_encoder_quark(), 0,
85 "neither bitrate nor quality defined "
86 "at line %i",
87 param->line);
88 return false;
91 encoder->quality = -2.0;
92 encoder->bitrate = g_ascii_strtoll(value, &endptr, 10);
94 if (*endptr != '\0' || encoder->bitrate <= 0) {
95 g_set_error(error, lame_encoder_quark(), 0,
96 "bitrate at line %i should be a positive integer",
97 param->line);
98 return false;
102 return true;
105 static struct encoder *
106 lame_encoder_init(const struct config_param *param, GError **error)
108 struct lame_encoder *encoder;
110 encoder = g_new(struct lame_encoder, 1);
111 encoder_struct_init(&encoder->encoder, &lame_encoder_plugin);
113 /* load configuration from "param" */
114 if (!lame_encoder_configure(encoder, param, error)) {
115 /* configuration has failed, roll back and return error */
116 g_free(encoder);
117 return NULL;
120 return &encoder->encoder;
123 static void
124 lame_encoder_finish(struct encoder *_encoder)
126 struct lame_encoder *encoder = (struct lame_encoder *)_encoder;
128 /* the real liblame cleanup was already performed by
129 lame_encoder_close(), so no real work here */
130 g_free(encoder);
133 static bool
134 lame_encoder_setup(struct lame_encoder *encoder, GError **error)
136 if (encoder->quality >= -1.0) {
137 /* a quality was configured (VBR) */
139 if (0 != lame_set_VBR(encoder->gfp, vbr_rh)) {
140 g_set_error(error, lame_encoder_quark(), 0,
141 "error setting lame VBR mode");
142 return false;
144 if (0 != lame_set_VBR_q(encoder->gfp, encoder->quality)) {
145 g_set_error(error, lame_encoder_quark(), 0,
146 "error setting lame VBR quality");
147 return false;
149 } else {
150 /* a bit rate was configured */
152 if (0 != lame_set_brate(encoder->gfp, encoder->bitrate)) {
153 g_set_error(error, lame_encoder_quark(), 0,
154 "error setting lame bitrate");
155 return false;
159 if (0 != lame_set_num_channels(encoder->gfp,
160 encoder->audio_format.channels)) {
161 g_set_error(error, lame_encoder_quark(), 0,
162 "error setting lame num channels");
163 return false;
166 if (0 != lame_set_in_samplerate(encoder->gfp,
167 encoder->audio_format.sample_rate)) {
168 g_set_error(error, lame_encoder_quark(), 0,
169 "error setting lame sample rate");
170 return false;
173 if (0 > lame_init_params(encoder->gfp)) {
174 g_set_error(error, lame_encoder_quark(), 0,
175 "error initializing lame params");
176 return false;
179 return true;
182 static bool
183 lame_encoder_open(struct encoder *_encoder, struct audio_format *audio_format,
184 GError **error)
186 struct lame_encoder *encoder = (struct lame_encoder *)_encoder;
188 audio_format->format = SAMPLE_FORMAT_S16;
189 audio_format->channels = 2;
191 encoder->audio_format = *audio_format;
193 encoder->gfp = lame_init();
194 if (encoder->gfp == NULL) {
195 g_set_error(error, lame_encoder_quark(), 0,
196 "lame_init() failed");
197 return false;
200 if (!lame_encoder_setup(encoder, error)) {
201 lame_close(encoder->gfp);
202 return false;
205 encoder->buffer_length = 0;
207 return true;
210 static void
211 lame_encoder_close(struct encoder *_encoder)
213 struct lame_encoder *encoder = (struct lame_encoder *)_encoder;
215 lame_close(encoder->gfp);
218 static bool
219 lame_encoder_write(struct encoder *_encoder,
220 const void *data, size_t length,
221 G_GNUC_UNUSED GError **error)
223 struct lame_encoder *encoder = (struct lame_encoder *)_encoder;
224 unsigned num_frames;
225 float *left, *right;
226 const int16_t *src = (const int16_t*)data;
227 unsigned int i;
228 int bytes_out;
230 assert(encoder->buffer_length == 0);
232 num_frames =
233 length / audio_format_frame_size(&encoder->audio_format);
234 left = g_malloc(sizeof(left[0]) * num_frames);
235 right = g_malloc(sizeof(right[0]) * num_frames);
237 /* this is for only 16-bit audio */
239 for (i = 0; i < num_frames; i++) {
240 left[i] = *src++;
241 right[i] = *src++;
244 bytes_out = lame_encode_buffer_float(encoder->gfp, left, right,
245 num_frames, encoder->buffer,
246 sizeof(encoder->buffer));
248 g_free(left);
249 g_free(right);
251 if (bytes_out < 0) {
252 g_set_error(error, lame_encoder_quark(), 0,
253 "lame encoder failed");
254 return false;
257 encoder->buffer_length = (size_t)bytes_out;
258 return true;
261 static size_t
262 lame_encoder_read(struct encoder *_encoder, void *dest, size_t length)
264 struct lame_encoder *encoder = (struct lame_encoder *)_encoder;
266 if (length > encoder->buffer_length)
267 length = encoder->buffer_length;
269 memcpy(dest, encoder->buffer, length);
271 encoder->buffer_length -= length;
272 memmove(encoder->buffer, encoder->buffer + length,
273 encoder->buffer_length);
275 return length;
278 static const char *
279 lame_encoder_get_mime_type(G_GNUC_UNUSED struct encoder *_encoder)
281 return "audio/mpeg";
284 const struct encoder_plugin lame_encoder_plugin = {
285 .name = "lame",
286 .init = lame_encoder_init,
287 .finish = lame_encoder_finish,
288 .open = lame_encoder_open,
289 .close = lame_encoder_close,
290 .write = lame_encoder_write,
291 .read = lame_encoder_read,
292 .get_mime_type = lame_encoder_get_mime_type,