1 /*
2 * cdda - CD Digital Audio support
3 *
4 * Copyright (C) 1993-2004 Ti Kan
5 * E-mail: xmcd@amb.org
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21 #ifndef lint
22 static char *_if_flac_c_ident_ = "@(#)if_flac.c 7.19 03/12/12";
23 #endif
24
25 #include "common_d/appenv.h"
26 #include "common_d/version.h"
27 #include "common_d/util.h"
28 #include "libdi_d/libdi.h"
29 #include "cdda_d/cdda.h"
30
31 #if defined(CDDA_SUPPORTED) && defined(HAS_FLAC)
32
33 #include "cdinfo_d/cdinfo.h"
34 #include "cdda_d/wr_gen.h"
35 #include "cdda_d/if_flac.h"
36
37 /* Hack: use our own FLAC types instead of using those from <FLAC/ordinals.h>
38 * to be independent of the compiler that was used to build the FLAC library.
39 * This is necessary to resolve a conflict on some platforms where FLAC was
40 * compiled with gcc (which has "long long"), but this file is being compiled
41 * with a compiler that does not have a 64-bit integer type.
42 */
43 #define FLAC__ORDINALS_H /* Override <FLAC/ordinals.h> */
44
45 typedef int FLAC__bool;
46 typedef byte_t FLAC__uint8;
47 typedef sbyte_t FLAC__int8;
48 typedef word16_t FLAC__uint16;
49 typedef sword16_t FLAC__int16;
50 typedef word32_t FLAC__uint32;
51 typedef sword32_t FLAC__int32;
52 typedef word64_t FLAC__uint64;
53 typedef sword64_t FLAC__int64;
54 typedef byte_t FLAC__byte;
55 typedef float FLAC__real;
56
57 #include <FLAC/format.h>
58 #include <FLAC/metadata.h>
59 #include <FLAC/stream_encoder.h>
60
61
62 extern appdata_t app_data;
63 extern FILE *errfp;
64 extern cdda_client_t *cdda_clinfo;
65
66 extern char *tagcomment; /* Tag comment */
67
68
69 /* Convenience macros */
70 #ifdef MIN
71 #undef MIN
72 #endif
73 #define MIN(x,y) (((x) < (y)) ? (x) : (y))
74
75 #ifdef MAX
76 #undef MAX
77 #endif
78 #define MAX(x,y) (((x) > (y)) ? (x) : (y))
79
80
81 /* Max number of metadata blocks */
82 #define META_MAXBLOCKS 8
83
84
85 /* Container union for encoder instance pointers */
86 typedef union {
87 FLAC__StreamEncoder *st; /* Stream encoder */
88 } flac_desc_t;
89
90
91 /* Structure of user-adjustable parameters */
92 typedef struct {
93 FLAC__bool mid_side, /* Enable mid/side stereo */
94 adap_ms, /* Enable adaptive mid/side stereo */
95 exh_srch, /* Enable exhaustive model search */
96 vfy_mode, /* Enable verify mode */
97 qlp_srch; /* Enable LP coeff quant search */
98 unsigned int lpc_order, /* LPC order */
99 block_sz; /* Block size */
100 int min_rpo, /* Minimum residual partition order */
101 max_rpo; /* Maximum residual partition order */
102 } flac_parms_t;
103
104
105 /* Pointers to wide samples buffers for each channel */
106 STATIC FLAC__int32 *fenc_buf[2] = { NULL, NULL };
107 STATIC FLAC__StreamMetadata **flac_mlist = NULL;
108 STATIC int flac_mblks = 0;
109
110
111 /*
112 * if_flac_write_callback
113 * FLAC stream encoder write callback function
114 *
115 * Args:
116 * stp - Stream encoder instance descriptor
117 * buf - Output data buffer
118 * len - data length
119 * samples - number of samples
120 * frame - Current frame
121 * client_data - Callback data
122 *
123 * Return:
124 * FLAC__STREAM_ENCODER_WRITE_STATUS_OK - success
125 * FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR - failure
126 */
127 /*ARGSUSED*/
128 STATIC FLAC__StreamEncoderWriteStatus
if_flac_write_callback(const FLAC__StreamEncoder * stp,const FLAC__byte * buf,unsigned int len,unsigned int samples,unsigned int frame,void * client_data)129 if_flac_write_callback(
130 const FLAC__StreamEncoder *stp,
131 const FLAC__byte *buf,
132 unsigned int len,
133 unsigned int samples,
134 unsigned int frame,
135 void *client_data
136 )
137 {
138 gen_desc_t *gdp = (gen_desc_t *) client_data;
139
140 if (buf == NULL || len == 0)
141 /* Nothing to do */
142 return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
143
144 /* Write out the encoded data */
145 gdp->flags |= GDESC_WRITEOUT;
146 if (!gen_write_chunk(gdp, (byte_t *) buf, (size_t) len))
147 return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
148
149 return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
150 }
151
152
153 /*
154 * if_flac_metadata_callback
155 * FLAC stream encoder metadata callback function
156 *
157 * Args:
158 * skp - Encoder instance descriptor
159 * data - Metadata buffer
160 * client_data - Callback data
161 *
162 * Return:
163 * Nothing.
164 */
165 /*ARGSUSED*/
166 STATIC FLAC__StreamEncoderSeekStatus
if_flac_metadata_callback(const FLAC__StreamEncoder * skp,FLAC__uint64 offset,void * client_data)167 if_flac_metadata_callback(
168 const FLAC__StreamEncoder *skp,
169 FLAC__uint64 offset,
170 void *client_data
171 )
172 {
173 gen_desc_t *gdp = (gen_desc_t *) client_data;
174 off_t val;
175
176 val = (off_t) ASSIGN32(offset);
177
178 if (gen_seek(gdp, val, SEEK_SET))
179 return FLAC__STREAM_ENCODER_SEEK_STATUS_OK;
180 else
181 return FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR;
182 }
183
184
185 /*
186 * if_flac_addseek_spaced
187 * Add spaced seek points template to the seektable metadata block.
188 * A seek point is added to approximately each 10 seconds of audio.
189 *
190 * Args:
191 * gdp - Pointer to the gen_desc_t structure
192 * mdp - The metadata descriptor
193 * cdi - Pointer to the cd_info_t structure
194 *
195 * Return:
196 * Nothing.
197 */
198 STATIC void
if_flac_addseek_spaced(gen_desc_t * gdp,FLAC__StreamMetadata * mdp,cd_info_t * cdi)199 if_flac_addseek_spaced(
200 gen_desc_t *gdp,
201 FLAC__StreamMetadata *mdp,
202 cd_info_t *cdi
203 )
204 {
205 FLAC__bool ret;
206 FLAC__uint64 val64;
207 unsigned int nsectors,
208 nsamples,
209 nseekpts;
210
211 nsectors = (unsigned int) cdi->end_lba - cdi->start_lba + 1;
212 nsamples = (unsigned int) (nsectors / FRAME_PER_SEC) * 44100;
213 nseekpts = nsectors / (FRAME_PER_SEC * 10);
214
215 if (nseekpts == 0)
216 return;
217
218 val64 = ASSIGN64(nsamples);
219
220 ret = FLAC__metadata_object_seektable_template_append_spaced_points(
221 mdp, nseekpts, val64
222 );
223 if (!ret) {
224 (void) strcpy(gdp->cdp->i->msgbuf,
225 "if_flac_addseek_spaced: "
226 "Failed inserting spaced seek point.");
227 DBGPRN(DBG_SND)(errfp, "%s\n", gdp->cdp->i->msgbuf);
228 return;
229 }
230
231 ret = FLAC__metadata_object_seektable_template_sort(mdp, FALSE);
232 if (!ret) {
233 (void) strcpy(gdp->cdp->i->msgbuf,
234 "if_flac_addseek_spaced: "
235 "Failed sorting the seek table.");
236 DBGPRN(DBG_SND)(errfp, "%s\n", gdp->cdp->i->msgbuf);
237 }
238 }
239
240
241 /*
242 * if_flac_addseek_tracks
243 * Add start-of-track seek points template to the seektable metadata
244 * block.
245 *
246 * Args:
247 * gdp - Pointer to the gen_desc_t structure
248 * mdp - The metadata descriptor
249 * cdi - Pointer to the cd_info_t structure
250 * s - Pointer to the curstat_t structure
251 *
252 * Return:
253 * Nothing.
254 */
255 STATIC void
if_flac_addseek_tracks(gen_desc_t * gdp,FLAC__StreamMetadata * mdp,cd_info_t * cdi,curstat_t * s)256 if_flac_addseek_tracks(
257 gen_desc_t *gdp,
258 FLAC__StreamMetadata *mdp,
259 cd_info_t *cdi,
260 curstat_t *s
261 )
262 {
263 FLAC__bool ret;
264 FLAC__uint64 val64;
265 unsigned int start,
266 end,
267 nsectors,
268 nsamples,
269 seekpt;
270 int i,
271 n;
272
273 seekpt = 0;
274 for (i = n = 0; i < (int) s->tot_trks; i++) {
275 if (cdi->end_lba < s->trkinfo[i].addr ||
276 cdi->start_lba > s->trkinfo[i].addr)
277 continue;
278
279 start = (unsigned int) MAX(s->trkinfo[i].addr, cdi->start_lba);
280 end = (unsigned int) MIN(s->trkinfo[i+1].addr, cdi->end_lba);
281 nsectors = end - start + 1;
282 nsamples = (unsigned int) (nsectors / FRAME_PER_SEC) * 44100;
283
284 if (n++ > 0)
285 seekpt += nsamples;
286
287 val64 = ASSIGN64(seekpt);
288
289 ret = FLAC__metadata_object_seektable_template_append_point(
290 mdp, val64
291 );
292 if (!ret) {
293 (void) sprintf(gdp->cdp->i->msgbuf,
294 "if_flac_addseek_tracks: "
295 "Failed adding seek point for track %d.",
296 (int) s->trkinfo[i].trkno);
297 DBGPRN(DBG_SND)(errfp, "%s\n", gdp->cdp->i->msgbuf);
298 }
299 }
300
301 ret = FLAC__metadata_object_seektable_template_sort(mdp, FALSE);
302 if (!ret) {
303 (void) strcpy(gdp->cdp->i->msgbuf,
304 "if_flac_addseek_tracks: "
305 "Failed sorting the seek table.");
306 DBGPRN(DBG_SND)(errfp, "%s\n", gdp->cdp->i->msgbuf);
307 }
308 }
309
310
311 /*
312 * if_flac_addtagent
313 * Add one entry into the vorbis comment metadata block.
314 *
315 * Args:
316 * gdp - Pointer to the gen_desc_t structure
317 * mdp - The metadata descriptor
318 * attr - Attribute name string
319 * val - Value string name
320 *
321 * Return:
322 * Nothing.
323 */
324 STATIC void
if_flac_addtagent(gen_desc_t * gdp,FLAC__StreamMetadata * mdp,char * attr,char * val)325 if_flac_addtagent(
326 gen_desc_t *gdp,
327 FLAC__StreamMetadata *mdp,
328 char *attr,
329 char *val
330 )
331 {
332 FLAC__StreamMetadata_VorbisComment_Entry ent;
333 FLAC__bool ret;
334 char txtstr[STR_BUF_SZ * 2];
335
336 /* Vorbis comments should be encoded in UTF-8 so we don't need
337 * any conversion here.
338 */
339
340 (void) sprintf(txtstr, "%.16s=%.100s", attr, val);
341 ent.entry = (FLAC__byte *) txtstr;
342 ent.length = (FLAC__uint32) strlen(txtstr);
343
344 ret = FLAC__metadata_object_vorbiscomment_insert_comment(
345 mdp, mdp->data.vorbis_comment.num_comments, ent, TRUE
346 );
347 if (!ret) {
348 (void) sprintf(gdp->cdp->i->msgbuf,
349 "if_flac_addtagent: "
350 "Failed inserting vorbis comment: attr=[%s]",
351 attr);
352 DBGPRN(DBG_SND)(errfp, "%s\n", gdp->cdp->i->msgbuf);
353 }
354 }
355
356
357 /*
358 * if_flac_addmeta
359 * Initialize and set the metadata areas of the FLAC output.
360 *
361 * Args:
362 * gdp - Pointer to the gen_desc_t structure
363 * ufdp - Pointer to the FLAC descriptor union
364 *
365 * Return:
366 * Nothing.
367 */
368 STATIC void
if_flac_addmeta(gen_desc_t * gdp,flac_desc_t * ufdp)369 if_flac_addmeta(gen_desc_t *gdp, flac_desc_t *ufdp)
370 {
371 FLAC__StreamMetadata *mdp;
372 FLAC__bool ret;
373 curstat_t *s = cdda_clinfo->curstat_addr();
374 cdinfo_incore_t *cdp = cdinfo_addr();
375 int i,
376 idx = (int) gdp->cdp->i->trk_idx;
377 size_t listsz;
378 char tmpstr[32];
379
380 listsz = sizeof(FLAC__StreamMetadata *) * META_MAXBLOCKS;
381
382 flac_mlist = (FLAC__StreamMetadata **) MEM_ALLOC("flac_mlist", listsz);
383 if (flac_mlist == NULL) {
384 (void) strcpy(gdp->cdp->i->msgbuf,
385 "if_flac_addmeta: Out of memory.");
386 DBGPRN(DBG_SND)(errfp, "%s\n", gdp->cdp->i->msgbuf);
387 return;
388 }
389 (void) memset(flac_mlist, 0, listsz);
390 flac_mblks = 0;
391
392 /* Application-specific metadata */
393 mdp = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION);
394 if (mdp == NULL) {
395 (void) strcpy(gdp->cdp->i->msgbuf,
396 "if_flac_addmeta: "
397 "Failed creating application metadata block.");
398 DBGPRN(DBG_SND)(errfp, "%s\n", gdp->cdp->i->msgbuf);
399 }
400 else {
401 char data[STR_BUF_SZ * 4];
402
403 flac_mlist[flac_mblks++] = mdp;
404
405 /* Set the application ID - This has been registered
406 * with the FLAC developers.
407 */
408 (void) memcpy(mdp->data.application.id, "xmcd", 4);
409
410 /* For future expansion: just some app information
411 * in here for now.
412 */
413 (void) sprintf(data, "%s.%s.%s\n%s\n%s\n%s\n",
414 VERSION_MAJ, VERSION_MIN, VERSION_TEENY,
415 COPYRIGHT, EMAIL, XMCD_URL
416 );
417
418 ret = FLAC__metadata_object_application_set_data(
419 mdp, (FLAC__byte *) data, (unsigned) strlen(data), TRUE
420 );
421 if (!ret) {
422 (void) strcpy(gdp->cdp->i->msgbuf,
423 "if_flac_addmeta: "
424 "Failed setting application metadata.");
425 DBGPRN(DBG_SND)(errfp, "%s\n", gdp->cdp->i->msgbuf);
426 }
427 }
428
429 /* Seek table metadata */
430 if ((gdp->flags & GDESC_ISPIPE) == 0) {
431 mdp = FLAC__metadata_object_new(FLAC__METADATA_TYPE_SEEKTABLE);
432 if (mdp == NULL) {
433 (void) strcpy(gdp->cdp->i->msgbuf,
434 "if_flac_addmeta: "
435 "Failed creating seektable metadata block.");
436 DBGPRN(DBG_SND)(errfp, "%s\n", gdp->cdp->i->msgbuf);
437 }
438 else {
439 cd_info_t *cdi = gdp->cdp->i;
440
441 flac_mlist[flac_mblks++] = mdp;
442
443 if (app_data.cdda_trkfile) {
444 /* Insert evenly spaced seek points */
445 if_flac_addseek_spaced(gdp, mdp, cdi);
446 }
447 else {
448 /* Insert seek points at start of tracks */
449 if_flac_addseek_tracks(gdp, mdp, cdi, s);
450 }
451 }
452 }
453
454 /* Vorbis comment metadata */
455 if (app_data.add_tag) {
456 mdp = FLAC__metadata_object_new(
457 FLAC__METADATA_TYPE_VORBIS_COMMENT
458 );
459 if (mdp == NULL) {
460 (void) strcpy(gdp->cdp->i->msgbuf,
461 "if_flac_addmeta: "
462 "Failed creating vorbis metadata block.");
463 DBGPRN(DBG_SND)(errfp, "%s\n", gdp->cdp->i->msgbuf);
464 }
465 else {
466 flac_mlist[flac_mblks++] = mdp;
467
468 mdp->data.vorbis_comment.num_comments = 0;
469
470 if (cdp->disc.title != NULL)
471 if_flac_addtagent(gdp, mdp, "ALBUM",
472 cdp->disc.title);
473
474 if (app_data.cdda_trkfile &&
475 cdp->track[idx].artist != NULL)
476 if_flac_addtagent(gdp, mdp, "ARTIST",
477 cdp->track[idx].artist);
478 else
479 if_flac_addtagent(gdp, mdp, "ARTIST",
480 cdp->disc.artist);
481
482 if (app_data.cdda_trkfile &&
483 cdp->track[idx].title != NULL)
484 if_flac_addtagent(gdp, mdp, "TITLE",
485 cdp->track[idx].title);
486 else if (cdp->disc.title != NULL)
487 if_flac_addtagent(gdp, mdp, "TITLE",
488 cdp->disc.title);
489
490 if (app_data.cdda_trkfile &&
491 cdp->track[idx].year != NULL)
492 if_flac_addtagent(gdp, mdp, "DATE",
493 cdp->track[idx].year);
494 else if (cdp->disc.year != NULL)
495 if_flac_addtagent(gdp, mdp, "DATE",
496 cdp->disc.year);
497
498 if (app_data.cdda_trkfile &&
499 cdp->track[idx].genre != NULL)
500 if_flac_addtagent(gdp, mdp, "GENRE",
501 cdinfo_genre_name(cdp->track[idx].genre));
502 else if (cdp->disc.genre != NULL)
503 if_flac_addtagent(gdp, mdp, "GENRE",
504 cdinfo_genre_name(cdp->disc.genre));
505
506 if (app_data.cdda_trkfile &&
507 cdp->track[idx].label != NULL)
508 if_flac_addtagent(gdp, mdp, "ORGANIZATION",
509 cdp->track[idx].label);
510 else if (cdp->disc.label != NULL)
511 if_flac_addtagent(gdp, mdp, "ORGANIZATION",
512 cdp->disc.label);
513
514 if (app_data.cdda_trkfile) {
515 (void) sprintf(tmpstr, "%d",
516 (int) s->trkinfo[idx].trkno);
517 if_flac_addtagent(gdp, mdp, "TRACKNUMBER",
518 tmpstr);
519
520 if (cdp->track[idx].bpm != NULL) {
521 if_flac_addtagent(gdp, mdp, "BPM",
522 cdp->track[idx].bpm);
523 }
524
525 if (cdp->track[idx].isrc != NULL) {
526 if_flac_addtagent(gdp, mdp, "ISRC",
527 cdp->track[idx].isrc);
528 }
529 }
530 else for (i = 0; i < (int) s->tot_trks; i++) {
531 cd_info_t *cdi = gdp->cdp->i;
532
533 if (cdi->end_lba < s->trkinfo[i].addr ||
534 cdi->start_lba > s->trkinfo[i].addr)
535 continue;
536
537 if (cdp->track[i].artist != NULL) {
538 (void) sprintf(tmpstr,
539 "TRACK%02dARTIST",
540 (int) s->trkinfo[i].trkno
541 );
542 if_flac_addtagent(gdp, mdp, tmpstr,
543 cdp->track[i].artist
544 );
545 }
546 if (cdp->track[i].title != NULL) {
547 (void) sprintf(tmpstr,
548 "TRACK%02dTITLE",
549 (int) s->trkinfo[i].trkno
550 );
551 if_flac_addtagent(gdp, mdp, tmpstr,
552 cdp->track[i].title
553 );
554 }
555 }
556
557 if (s->mcn[0] != '\0')
558 if_flac_addtagent(gdp, mdp, "MCN", s->mcn);
559
560 (void) sprintf(tmpstr, "%08x", (int) cdp->discid);
561 if_flac_addtagent(gdp, mdp, "XMCDDISCID", tmpstr);
562
563 if_flac_addtagent(gdp, mdp, "ENCODER", tagcomment);
564 }
565 }
566
567 if (flac_mblks == 0)
568 return; /* No metadata to set */
569
570 ret = FLAC__stream_encoder_set_metadata(
571 ufdp->st, flac_mlist, flac_mblks
572 );
573 if (!ret) {
574 (void) strcpy(gdp->cdp->i->msgbuf,
575 "if_flac_addmeta: Failed setting metadata.");
576 DBGPRN(DBG_SND)(errfp, "%s\n", gdp->cdp->i->msgbuf);
577 }
578 }
579
580
581 /*
582 * if_flac_encoder_setup
583 * Create and set up the FLAC stream encoder.
584 *
585 * Args:
586 * gdp - Pointer to the gen_desc_t structure
587 * ufdp - Pointer to the flac_desc_t structure
588 * pp - Pointer to the flac_parms_t structure
589 *
590 * Return:
591 * TRUE - success
592 * FALSE - failure
593 */
594 STATIC bool_t
if_flac_encoder_setup(gen_desc_t * gdp,flac_desc_t * ufdp,flac_parms_t * pp)595 if_flac_encoder_setup(
596 gen_desc_t *gdp,
597 flac_desc_t *ufdp,
598 flac_parms_t *pp
599 )
600 {
601 FLAC__StreamEncoder *stp;
602 FLAC__StreamEncoderState enc_state;
603 FLAC__uint64 val;
604 FLAC__bool ret;
605
606 ufdp->st = stp = FLAC__stream_encoder_new();
607 if (stp == NULL) {
608 (void) strcpy(gdp->cdp->i->msgbuf,
609 "if_flac_encoder_setup: "
610 "FLAC encoder instantiation failed.");
611 DBGPRN(DBG_SND)(errfp, "%s\n", gdp->cdp->i->msgbuf);
612 return FALSE;
613 }
614
615 /* Set some basic parameters */
616
617 ret = FLAC__stream_encoder_set_channels(stp, 2);
618 if (!ret) {
619 (void) strcpy(gdp->cdp->i->msgbuf,
620 "if_flac_encoder_setup: "
621 "Failed setting channels.");
622 DBGPRN(DBG_SND)(errfp, "%s\n", gdp->cdp->i->msgbuf);
623 return FALSE;
624 }
625
626 ret = FLAC__stream_encoder_set_bits_per_sample(stp, 16);
627 if (!ret) {
628 (void) strcpy(gdp->cdp->i->msgbuf,
629 "if_flac_encoder_setup: "
630 "Failed setting bits per sample.");
631 DBGPRN(DBG_SND)(errfp, "%s\n", gdp->cdp->i->msgbuf);
632 return FALSE;
633 }
634
635 ret = FLAC__stream_encoder_set_sample_rate(stp, 44100);
636 if (!ret) {
637 (void) strcpy(gdp->cdp->i->msgbuf,
638 "if_flac_encoder_setup: "
639 "Failed setting sample rate.");
640 DBGPRN(DBG_SND)(errfp, "%s\n", gdp->cdp->i->msgbuf);
641 return FALSE;
642 }
643
644 val = ASSIGN64(gdp->datalen >> 2);
645 ret = FLAC__stream_encoder_set_total_samples_estimate(stp, val);
646 if (!ret) {
647 (void) strcpy(gdp->cdp->i->msgbuf,
648 "if_flac_encoder_setup: "
649 "Failed setting samples estimate.");
650 DBGPRN(DBG_SND)(errfp, "%s\n", gdp->cdp->i->msgbuf);
651 return FALSE;
652 }
653
654 ret = FLAC__stream_encoder_set_streamable_subset(stp, TRUE);
655 if (!ret) {
656 (void) strcpy(gdp->cdp->i->msgbuf,
657 "if_flac_encoder_setup: "
658 "Failed setting streamable subset.");
659 DBGPRN(DBG_SND)(errfp, "%s\n", gdp->cdp->i->msgbuf);
660 return FALSE;
661 }
662
663 ret = FLAC__stream_encoder_set_do_qlp_coeff_prec_search(
664 stp, pp->qlp_srch
665 );
666 if (!ret) {
667 (void) strcpy(gdp->cdp->i->msgbuf,
668 "if_flac_encoder_setup: "
669 "Failed setting LP coefficient quantization search."
670 );
671 DBGPRN(DBG_SND)(errfp, "%s\n", gdp->cdp->i->msgbuf);
672 return FALSE;
673 }
674
675 /* Just use default for now
676 ret = FLAC__stream_encoder_set_qlp_coeff_precision(stp, 0);
677 */
678
679 ret = FLAC__stream_encoder_set_verify(stp, pp->vfy_mode);
680 if (!ret) {
681 (void) strcpy(gdp->cdp->i->msgbuf,
682 "if_flac_encoder_setup: "
683 "Failed setting verify mode.");
684 DBGPRN(DBG_SND)(errfp, "%s\n", gdp->cdp->i->msgbuf);
685 return FALSE;
686 }
687
688 ret = FLAC__stream_encoder_set_max_lpc_order(stp, pp->lpc_order);
689 if (!ret) {
690 (void) strcpy(gdp->cdp->i->msgbuf,
691 "if_flac_encoder_setup: "
692 "Failed setting max LPC order.");
693 DBGPRN(DBG_SND)(errfp, "%s\n", gdp->cdp->i->msgbuf);
694 return FALSE;
695 }
696
697 ret = FLAC__stream_encoder_set_blocksize(stp, pp->block_sz);
698 if (!ret) {
699 (void) strcpy(gdp->cdp->i->msgbuf,
700 "if_flac_encoder_setup: "
701 "Failed setting block size.");
702 DBGPRN(DBG_SND)(errfp, "%s\n", gdp->cdp->i->msgbuf);
703 return FALSE;
704 }
705
706 ret = FLAC__stream_encoder_set_do_mid_side_stereo(stp, pp->mid_side);
707 if (!ret) {
708 (void) strcpy(gdp->cdp->i->msgbuf,
709 "if_flac_encoder_setup: "
710 "Failed setting M/S stereo.");
711 DBGPRN(DBG_SND)(errfp, "%s\n", gdp->cdp->i->msgbuf);
712 return FALSE;
713 }
714
715 ret = FLAC__stream_encoder_set_loose_mid_side_stereo(stp, pp->adap_ms);
716 if (!ret) {
717 (void) strcpy(gdp->cdp->i->msgbuf,
718 "if_flac_encoder_setup: "
719 "Failed setting adaptive M/S stereo.");
720 DBGPRN(DBG_SND)(errfp, "%s\n", gdp->cdp->i->msgbuf);
721 return FALSE;
722 }
723
724 if (pp->min_rpo >= 0) {
725 ret = FLAC__stream_encoder_set_min_residual_partition_order(
726 stp, (unsigned int) pp->min_rpo
727 );
728 if (!ret) {
729 (void) strcpy(gdp->cdp->i->msgbuf,
730 "if_flac_encoder_setup: "
731 "Failed setting minimum RPO.");
732 DBGPRN(DBG_SND)(errfp, "%s\n", gdp->cdp->i->msgbuf);
733 return FALSE;
734 }
735 }
736
737 if (pp->max_rpo >= 0) {
738 ret = FLAC__stream_encoder_set_max_residual_partition_order(
739 stp, (unsigned int) pp->max_rpo
740 );
741 if (!ret) {
742 (void) strcpy(gdp->cdp->i->msgbuf,
743 "if_flac_encoder_setup: "
744 "Failed setting maximum RPO.");
745 DBGPRN(DBG_SND)(errfp, "%s\n", gdp->cdp->i->msgbuf);
746 return FALSE;
747 }
748 }
749
750 ret = FLAC__stream_encoder_set_do_exhaustive_model_search(
751 stp, pp->exh_srch
752 );
753 if (!ret) {
754 (void) strcpy(gdp->cdp->i->msgbuf,
755 "if_flac_encoder_setup: "
756 "Failed setting exhaustive model search.");
757 DBGPRN(DBG_SND)(errfp, "%s\n", gdp->cdp->i->msgbuf);
758 return FALSE;
759 }
760
761 /* Initialize and add metadata to FLAC output */
762 if_flac_addmeta(gdp, ufdp);
763
764 /* Initialize FLAC encoder */
765 enc_state = FLAC__stream_encoder_init_stream(
766 stp, if_flac_write_callback, NULL, NULL,
767 if_flac_metadata_callback, gdp
768 );
769 if (enc_state != FLAC__STREAM_ENCODER_INIT_STATUS_OK) {
770 (void) sprintf(gdp->cdp->i->msgbuf,
771 "if_flac_encoder_setup: Encoder init error: %s",
772 FLAC__stream_encoder_get_resolved_state_string(stp)
773 );
774 DBGPRN(DBG_SND)(errfp, "%s\n", gdp->cdp->i->msgbuf);
775 return FALSE;
776 }
777
778 /* Allocate wide samples buffers for the two channels */
779 fenc_buf[0] = (FLAC__int32 *) MEM_ALLOC(
780 "fenc_buf0",
781 (size_t) gdp->cdp->cds->chunk_bytes
782 );
783 if (fenc_buf[0] == NULL) {
784 (void) strcpy(gdp->cdp->i->msgbuf,
785 "if_flac_encoder_setup: Out of memory.");
786 DBGPRN(DBG_SND)(errfp, "%s\n", gdp->cdp->i->msgbuf);
787 return FALSE;
788 }
789 fenc_buf[1] = (FLAC__int32 *) MEM_ALLOC(
790 "fenc_buf1",
791 (size_t) gdp->cdp->cds->chunk_bytes
792 );
793 if (fenc_buf[1] == NULL) {
794 (void) strcpy(gdp->cdp->i->msgbuf,
795 "if_flac_encoder_setup: Out of memory.");
796 DBGPRN(DBG_SND)(errfp, "%s\n", gdp->cdp->i->msgbuf);
797 return FALSE;
798 }
799
800 return TRUE;
801 }
802
803
804 /*
805 * if_flac_init
806 * Initialize FLAC encoder and set up encoding parameters
807 *
808 * Args:
809 * gdp - Pointer to the gen_desc_t structure
810 *
811 * Return:
812 * FALSE - failure
813 * TRUE - success
814 */
815 bool_t
if_flac_init(gen_desc_t * gdp)816 if_flac_init(gen_desc_t *gdp)
817 {
818 FLAC__bool ret;
819 flac_desc_t *ufdp;
820 flac_parms_t parms;
821
822 /* Allocate descriptor */
823 ufdp = (flac_desc_t *) MEM_ALLOC("flac_desc_t", sizeof(flac_desc_t));
824 if (ufdp == NULL) {
825 (void) strcpy(gdp->cdp->i->msgbuf,
826 "if_flac_init: Out of memory.");
827 DBGPRN(DBG_SND)(errfp, "%s\n", gdp->cdp->i->msgbuf);
828 return FALSE;
829 }
830
831 gdp->aux = (void *) ufdp;
832
833 /* Set up adjustable parameters */
834
835 switch (app_data.comp_mode) {
836 case COMPMODE_3:
837 parms.qlp_srch = parms.vfy_mode = TRUE;
838 break;
839 case COMPMODE_2:
840 parms.qlp_srch = FALSE;
841 parms.vfy_mode = TRUE;
842 break;
843 case COMPMODE_1:
844 parms.qlp_srch = TRUE;
845 parms.vfy_mode = FALSE;
846 break;
847 case COMPMODE_0:
848 default:
849 parms.qlp_srch = parms.vfy_mode = FALSE;
850 break;
851 }
852
853 switch (app_data.comp_algo) {
854 case 10:
855 case 9:
856 parms.lpc_order = 12;
857 parms.block_sz = 4608;
858 parms.min_rpo = 6;
859 parms.max_rpo = -1;
860 parms.mid_side = TRUE;
861 parms.adap_ms = FALSE;
862 parms.exh_srch = TRUE;
863 break;
864 case 8:
865 parms.lpc_order = 8;
866 parms.block_sz = 4608;
867 parms.min_rpo = 6;
868 parms.max_rpo = -1;
869 parms.mid_side = TRUE;
870 parms.adap_ms = FALSE;
871 parms.exh_srch = TRUE;
872 break;
873 case 7:
874 parms.lpc_order = 8;
875 parms.block_sz = 4608;
876 parms.min_rpo = 4;
877 parms.max_rpo = -1;
878 parms.mid_side = TRUE;
879 parms.adap_ms = FALSE;
880 parms.exh_srch = FALSE;
881 break;
882 case 6:
883 parms.lpc_order = 8;
884 parms.block_sz = 4608;
885 parms.min_rpo = parms.max_rpo = 3;
886 parms.mid_side = TRUE;
887 parms.adap_ms = FALSE;
888 parms.exh_srch = FALSE;
889 break;
890 case 5:
891 parms.lpc_order = 8;
892 parms.block_sz = 4608;
893 parms.min_rpo = parms.max_rpo = 3;
894 parms.mid_side = parms.adap_ms = TRUE;
895 parms.exh_srch = FALSE;
896 break;
897 case 4:
898 parms.lpc_order = 6;
899 parms.block_sz = 4608;
900 parms.min_rpo = parms.max_rpo = 3;
901 parms.mid_side = parms.adap_ms = FALSE;
902 parms.exh_srch = FALSE;
903 break;
904 case 3:
905 parms.lpc_order = 0;
906 parms.block_sz = 1152;
907 parms.min_rpo = 3;
908 parms.max_rpo = -1;
909 parms.mid_side = TRUE;
910 parms.adap_ms = FALSE;
911 parms.exh_srch = FALSE;
912 break;
913 case 2:
914 parms.lpc_order = 0;
915 parms.block_sz = 1152;
916 parms.min_rpo = parms.max_rpo = 2;
917 parms.mid_side = TRUE;
918 parms.adap_ms = TRUE;
919 parms.exh_srch = FALSE;
920 break;
921 case 1:
922 default:
923 parms.lpc_order = 0;
924 parms.block_sz = 1152;
925 parms.min_rpo = parms.max_rpo = 2;
926 parms.mid_side = parms.adap_ms = FALSE;
927 parms.exh_srch = FALSE;
928 break;
929 }
930
931 /* Set up encoder */
932 ret = if_flac_encoder_setup(gdp, ufdp, &parms);
933
934 return (ret);
935 }
936
937
938 /*
939 * if_flac_encode_chunk
940 * Encodes the audio data using FLAC and write to the fd.
941 *
942 * Args:
943 * gdp - Pointer to the gen_desc_t structure
944 * data - Pointer to data
945 * len - Data length in bytes
946 *
947 * Return:
948 * FALSE - failure
949 * TRUE - success
950 */
951 bool_t
if_flac_encode_chunk(gen_desc_t * gdp,byte_t * data,size_t len)952 if_flac_encode_chunk(gen_desc_t *gdp, byte_t *data, size_t len)
953 {
954 flac_desc_t *ufdp;
955 FLAC__bool ret;
956 int i,
957 j,
958 samples;
959 sword16_t *p;
960
961 if (gdp == NULL || gdp->aux == NULL)
962 return FALSE;
963
964 if (data == NULL || len == 0)
965 /* Nothing to do */
966 return TRUE;
967
968 ufdp = (flac_desc_t *) gdp->aux;
969
970 /* De-interleave data and sign-extend into wide samples buffer */
971 samples = (len >> 2);
972 p = (sword16_t *)(void *) data;
973 for (i = 0, j = 0; i < samples; i++) {
974 fenc_buf[0][i] = (FLAC__int32) p[j++];
975 fenc_buf[1][i] = (FLAC__int32) p[j++];
976 }
977
978 DBGPRN(DBG_SND)(errfp, "\nEncoding %d samples\n", samples);
979
980 ret = FLAC__stream_encoder_process(
981 ufdp->st, (void *) fenc_buf, (unsigned int) samples
982 );
983 if (!ret) {
984 (void) strcpy(gdp->cdp->i->msgbuf,
985 "if_flac_encode_chunk: Process encoding failed.");
986 DBGPRN(DBG_SND)(errfp, "%s\n", gdp->cdp->i->msgbuf);
987 return FALSE;
988 }
989
990 return TRUE;
991 }
992
993
994 /*
995 * if_flac_halt
996 * Flush buffers and shut down FLAC encoder
997 *
998 * Args:
999 * gdp - Pointer to the gen_desc_t structure
1000 *
1001 * Return:
1002 * Nothing.
1003 */
1004 void
if_flac_halt(gen_desc_t * gdp)1005 if_flac_halt(gen_desc_t *gdp)
1006 {
1007 flac_desc_t *ufdp;
1008 int i;
1009
1010 if (gdp == NULL || gdp->aux == NULL)
1011 return;
1012
1013 ufdp = (flac_desc_t *) gdp->aux;
1014
1015 FLAC__stream_encoder_finish(ufdp->st);
1016 FLAC__stream_encoder_delete(ufdp->st);
1017
1018 MEM_FREE(ufdp);
1019 gdp->aux = NULL;
1020
1021 /* Deallocate metadata objects */
1022 for (i = 0; i < flac_mblks; i++) {
1023 if (flac_mlist[i] != NULL)
1024 FLAC__metadata_object_delete(flac_mlist[i]);
1025 }
1026 MEM_FREE(flac_mlist);
1027 flac_mlist = NULL;
1028 flac_mblks = 0;
1029
1030 /* Free wide samples buffers */
1031 if (fenc_buf[0] != NULL)
1032 MEM_FREE(fenc_buf[0]);
1033 if (fenc_buf[1] != NULL)
1034 MEM_FREE(fenc_buf[1]);
1035
1036 fenc_buf[0] = fenc_buf[1] = NULL;
1037 }
1038
1039 #endif /* CDDA_SUPPORTED HAS_FLAC */
1040
1041