source: roaraudio/roard/codecfilter_flac.c @ 6052:d48765b2475e

Last change on this file since 6052:d48765b2475e was 6052:d48765b2475e, checked in by phi, 9 years ago

updated copyright headers

File size: 10.4 KB
Line 
1//codecfilter_flac.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2015
5 *
6 *  This file is part of roard a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  RoarAudio is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 */
25
26#include "roard.h"
27#include <roaraudio/units.h>
28
29#ifdef ROAR_HAVE_LIBFLAC
30
31FLAC__StreamDecoderReadStatus cf_flac_cb_read(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data) {
32 struct codecfilter_flac_inst * self = client_data;
33 ssize_t ret;
34
35 ROAR_DBG("cf_flac_cb_read(decoder=%p, buffer=%p, bytes=%p{%u}, client_data=%p) = ?", decoder, buffer, bytes, *bytes, client_data);
36
37 ret = stream_vio_s_read(self->ss, buffer, *bytes);
38
39 self->decoder.readret = ret;
40
41 self->decoder.readc++;
42
43 if (ret == -1) {
44  *bytes = 0;
45
46#ifdef EAGAIN
47 if ( errno == EAGAIN ) {
48  ROAR_DBG("cf_flac_cb_read(decoder=%p, buffer=%p, bytes=%p{%u}, client_data=%p) = FLAC__STREAM_DECODER_READ_STATUS_CONTINUE", decoder, buffer, bytes, *bytes, client_data);
49  return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
50 }
51#endif
52
53  ROAR_DBG("cf_flac_cb_read(decoder=%p, buffer=%p, bytes=%p{%u}, client_data=%p) = FLAC__STREAM_DECODER_READ_STATUS_ABORT", decoder, buffer, bytes, *bytes, client_data);
54  return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
55 } else {
56  *bytes = ret;
57
58  if ( ret == 0 && self->decoder.readc == 1 ) {
59   ROAR_DBG("cf_flac_cb_read(decoder=%p, buffer=%p, bytes=%p{%u}, client_data=%p) = FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM", decoder, buffer, bytes, *bytes, client_data);
60   return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
61  }
62  ROAR_DBG("cf_flac_cb_read(decoder=%p, buffer=%p, bytes=%p{%u}, client_data=%p) = FLAC__STREAM_DECODER_READ_STATUS_CONTINUE", decoder, buffer, bytes, *bytes, client_data);
63  return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
64 }
65}
66
67FLAC__StreamDecoderWriteStatus cf_flac_cb_write(const FLAC__StreamDecoder * decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) {
68 struct codecfilter_flac_inst * self = client_data;
69 struct roar_buffer * buf;
70 struct roar_interleave is;
71 size_t buflen = _32BIT * frame->header.blocksize * frame->header.channels;
72 void * bufdata;
73 int32_t * c;
74 size_t i;
75 int32_t shift = 32 - frame->header.bits_per_sample;
76
77 ROAR_DBG("cf_flac_cb_write(decoder=%p, frame=%p, buffer=%p, client_data=%p) = ?", decoder, frame, buffer, client_data);
78
79 if ( roar_interl_init(&is, frame->header.channels, 32) == -1 ) {
80  ROAR_DBG("cf_flac_cb_write(decoder=%p, frame=%p, buffer=%p, client_data=%p) = FLAC__STREAM_DECODER_WRITE_STATUS_ABORT", decoder, frame, buffer, client_data);
81  return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
82 }
83
84 if ( roar_buffer_new_data(&buf, buflen, &bufdata) == -1 ) {
85  ROAR_DBG("cf_flac_cb_write(decoder=%p, frame=%p, buffer=%p, client_data=%p) = FLAC__STREAM_DECODER_WRITE_STATUS_ABORT", decoder, frame, buffer, client_data);
86  return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
87 }
88
89 roar_interl_encode_ext(&is, (void**)buffer, bufdata, buflen);
90
91 roar_interl_uninit(&is);
92
93 if ( shift ) {
94  buflen /= 4;
95  for (c = bufdata, i = 0; i < buflen; i++) {
96   c[i] <<= shift;
97  }
98 }
99
100 if ( self->decoder.written == NULL ) {
101  self->decoder.written = buf;
102 } else {
103  if ( roar_buffer_moveinto(self->decoder.written, &buf) == -1 ) {
104   roar_buffer_free(buf);
105   return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
106  }
107 }
108
109 ROAR_DBG("cf_flac_cb_write(decoder=%p, frame=%p, buffer=%p, client_data=%p) = FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE", decoder, frame, buffer, client_data);
110
111 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
112}
113
114void cf_flac_cb_metadata(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) {
115 struct codecfilter_flac_inst * self = client_data;
116 const FLAC__StreamMetadata_VorbisComment * vc;
117 FLAC__uint32 i;
118 struct roar_stream_rpg rpg;
119 const char * key, * value;
120 char keycopy[ROAR_META_MAX_NAMELEN];
121 int type;
122 float rpg_track = 0, rpg_album = 0, rpg_final = 0;
123
124 if ( metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT ) {
125  ROAR_DBG("cf_flac_cb_metadata(decoder=%p, metadata=%p, client_data=%p): have METADATA_TYPE_VORBIS_COMMENT", decoder, metadata, client_data);
126
127  stream_meta_clear(ROAR_STREAM(self->ss)->id);
128
129  vc = &(metadata->data.vorbis_comment);
130
131  for (i = 0; i < vc->num_comments; i++) {
132   //printf("c='%s'\n", vc->comments[i].entry);
133   key = (const char *)vc->comments[i].entry;
134   value = strstr(key, "=");
135   if ( value == NULL )
136    continue;
137
138   if ( (value - key + 1) > sizeof(keycopy) )
139    continue;
140
141   memcpy(keycopy, key, value - key);
142   keycopy[sizeof(keycopy)-1] = 0;
143   keycopy[value - key] = 0;
144
145   value++;
146
147   //printf("keycopy='%s', value='%s'\n", keycopy, value);
148
149   type = roar_meta_inttype(keycopy);
150   if ( type == -1 )
151    continue;
152
153   if ( stream_meta_add(ROAR_STREAM(self->ss)->id, type, "", value) == -1 ) {
154    ROAR_WARN("cf_flac_cb_metadata(..., client_data=%p{ROAR_STREAM(.ss)->id=%i}): Can not add meta data: %s",
155              self->ss, ROAR_STREAM(self->ss)->id, roar_error2str(roar_error));
156   }
157
158    if ( strcmp(keycopy, "REPLAYGAIN_TRACK_PEAK") == 0 ) {
159     rpg_track = 1/atof(value);
160/*
161    } else if ( strcmp(key, "REPLAYGAIN_TRACK_GAIN") == 0 ) {
162     rpg_track = powf(10, atof(value)/20);
163*/
164    } else if ( strcmp(keycopy, "REPLAYGAIN_ALBUM_PEAK") == 0 ) {
165     rpg_album = 1/atof(value);
166/*
167    } else if ( strcmp(key, "REPLAYGAIN_ALBUM_GAIN") == 0 ) {
168     rpg_album = powf(10, atof(value)/20);
169*/
170    }
171
172  }
173
174 if ( streams_get_rpg(ROAR_STREAM(self->ss)->id, &rpg) != -1 ) {
175  rpg_final = 0;
176
177  switch (rpg.mode) {
178   case ROAR_RPGMODE_NONE: rpg_final =  0.; break;
179   case ROAR_RPGMODE_USER: rpg_final = -1.; break;
180   case ROAR_RPGMODE_ALBUM: rpg_final = rpg_album; break;
181   case ROAR_RPGMODE_TRACK: rpg_final = rpg_track; break;
182   case ROAR_RPGMODE_ALBUMTRACK: rpg_final = rpg_album ? rpg_album : rpg_track; break;
183   case ROAR_RPGMODE_TRACKALBUM: rpg_final = rpg_track ? rpg_track : rpg_album; break;
184  }
185
186  if ( rpg_final > 0 ) {
187   self->ss->mixer.rpg_div = 2718;
188   self->ss->mixer.rpg_mul = (float)rpg_final*2718;
189  } else if ( !rpg_final ) {
190   self->ss->mixer.rpg_div = 1;
191   self->ss->mixer.rpg_mul = 1;
192  }
193 }
194
195  stream_meta_finalize(ROAR_STREAM(self->ss)->id);
196 }
197
198 ROAR_DBG("cf_flac_cb_metadata(decoder=%p, metadata=%p, client_data=%p) = (void)", decoder, metadata, client_data);
199}
200
201void cf_flac_cb_error(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) {
202 ROAR_DBG("cf_flac_cb_error(decoder=%p, status=%i, client_data=%p) = (void)", decoder, (int)status, client_data);
203}
204
205int cf_flac_open(CODECFILTER_USERDATA_T * inst, int codec,
206                                            struct roar_stream_server * info,
207                                            struct roar_codecfilter   * filter) {
208 struct codecfilter_flac_inst * self;
209
210 if ( ROAR_STREAM(info)->dir != ROAR_DIR_PLAY )
211  return -1;
212
213 self = roar_mm_malloc(sizeof(struct codecfilter_flac_inst));
214
215 if (self == NULL)
216  return -1;
217
218 memset(self, 0, sizeof(struct codecfilter_flac_inst));
219
220 self->ss = info;
221
222 self->decoder.decoder = FLAC__stream_decoder_new();
223
224 if ( self->decoder.decoder == NULL ) {
225  roar_mm_free(self);
226  return -1;
227 }
228
229#ifndef ROAR_HAVE_FLAC_VERSION_1_2_1
230 FLAC__stream_decoder_set_read_callback(self->decoder.decoder, cf_flac_cb_read);
231 FLAC__stream_decoder_set_write_callback(self->decoder.decoder, cf_flac_cb_write);
232 FLAC__stream_decoder_set_metadata_callback(self->decoder.decoder, cf_flac_cb_metadata);
233 FLAC__stream_decoder_set_error_callback(self->decoder.decoder, cf_flac_cb_error);
234 FLAC__stream_decoder_set_client_data(self->decoder.decoder, self);
235#endif
236
237 FLAC__stream_decoder_set_metadata_respond(self->decoder.decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT);
238
239#ifdef ROAR_HAVE_FLAC_VERSION_1_2_1
240 FLAC__stream_decoder_init_stream(self->decoder.decoder, cf_flac_cb_read, NULL, NULL, NULL, NULL, cf_flac_cb_write, cf_flac_cb_metadata, cf_flac_cb_error, self);
241#else
242 FLAC__stream_decoder_init(self->decoder.decoder);
243#endif
244
245 *inst = self;
246
247 return 0;
248}
249
250int cf_flac_close(CODECFILTER_USERDATA_T   inst) {
251 struct codecfilter_flac_inst * self = inst;
252
253 if ( self->decoder.decoder != NULL ) {
254  FLAC__stream_decoder_delete(self->decoder.decoder);
255 }
256
257 roar_mm_free(self);
258
259 return 0;
260}
261
262int cf_flac_write(CODECFILTER_USERDATA_T   inst, char * buf, int len);
263
264int cf_flac_read(CODECFILTER_USERDATA_T   inst, char * buf, int len) {
265 struct codecfilter_flac_inst * self = inst;
266 struct roar_audio_info * info = &(ROAR_STREAM(self->ss)->info);
267 struct roar_buffer_stats stats;
268 size_t ret;
269 FLAC__StreamDecoderState state;
270
271 if ( self->decoder.written == NULL ) {
272  stats.bytes = 0;
273 } else {
274  if ( roar_buffer_ring_stats(self->decoder.written, &stats) == -1 )
275   return -1;
276 }
277
278 self->decoder.readret = 1;
279 self->decoder.readc   = 0;
280
281 while ( self->decoder.readret > 0 && stats.bytes < len ) {
282  if ( !FLAC__stream_decoder_process_single(self->decoder.decoder) ) {
283   break;
284  }
285
286  state = FLAC__stream_decoder_get_state(self->decoder.decoder);
287
288  if ( state == FLAC__STREAM_DECODER_END_OF_STREAM || state == FLAC__STREAM_DECODER_ABORTED )
289   break;
290
291  if ( self->decoder.written == NULL && state == FLAC__STREAM_DECODER_READ_FRAME ) {
292   return -1;
293  }
294
295  if ( self->decoder.written == NULL ) {
296   stats.bytes = 0;
297  } else {
298   if ( roar_buffer_ring_stats(self->decoder.written, &stats) == -1 )
299    return -1;
300  }
301 }
302
303 if ( stats.bytes ) {
304  ret = len;
305
306  if ( roar_buffer_shift_out(&(self->decoder.written), buf, &ret) == -1 ) {
307   return -1;
308  }
309
310  info->codec    = ROAR_CODEC_DEFAULT;
311  info->bits     = 32;
312  info->channels = FLAC__stream_decoder_get_channels(self->decoder.decoder);
313  info->rate     = FLAC__stream_decoder_get_sample_rate(self->decoder.decoder);
314
315  return ret;
316 } else {
317  return self->decoder.readret == -1 ? -1 : 0;
318 }
319}
320
321int cf_flac_ctl(CODECFILTER_USERDATA_T   inst, int cmd, void * data);
322
323#endif
324
325//ll
Note: See TracBrowser for help on using the repository browser.