|
Lines 38-51
Link Here
|
| 38 |
|
38 |
|
| 39 |
#if defined(AU_FLAC_DLL) || defined(AU_OGGFLAC_DLL) |
39 |
#if defined(AU_FLAC_DLL) || defined(AU_OGGFLAC_DLL) |
| 40 |
#include <windows.h> |
40 |
#include <windows.h> |
| 41 |
#define FLAC__EXPORT_H /* don't include "OggFLAC/export.h" */ |
41 |
#include <FLAC/export.h> /* need export.h to figure out API version from FLAC_API_VERSION_CURRENT */ |
| 42 |
#define FLAC_API |
42 |
#undef FLAC_API |
| 43 |
#define OggFLAC__EXPORT_H /* don't include "FLAC/export.h" */ |
43 |
#undef OggFLAC_API |
| 44 |
#define OggFLAC_API |
|
|
| 45 |
#endif |
44 |
#endif |
| 46 |
|
45 |
|
| 47 |
#include <FLAC/all.h> |
46 |
#include <FLAC/all.h> |
| 48 |
#ifdef AU_OGGFLAC |
47 |
|
|
|
48 |
/* by LEGACY_FLAC we mean before FLAC 1.1.3 */ |
| 49 |
/* in FLAC 1.1.3, libOggFLAC is merged into libFLAC and all encoding layers are merged into the stream encoder */ |
| 50 |
#if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT < 8 |
| 51 |
#define LEGACY_FLAC |
| 52 |
#else |
| 53 |
#undef LEGACY_FLAC |
| 54 |
#endif |
| 55 |
|
| 56 |
#if defined(LEGACY_FLAC) && defined(AU_OGGFLAC) |
| 49 |
#include <OggFLAC/stream_encoder.h> |
57 |
#include <OggFLAC/stream_encoder.h> |
| 50 |
#endif |
58 |
#endif |
| 51 |
|
59 |
|
|
Lines 100-116
Link Here
|
| 100 |
unsigned long out_bytes; |
108 |
unsigned long out_bytes; |
| 101 |
union { |
109 |
union { |
| 102 |
FLAC__StreamEncoderState flac; |
110 |
FLAC__StreamEncoderState flac; |
|
|
111 |
#ifdef LEGACY_FLAC |
| 103 |
FLAC__SeekableStreamEncoderState s_flac; |
112 |
FLAC__SeekableStreamEncoderState s_flac; |
| 104 |
#ifdef AU_OGGFLAC |
113 |
#ifdef AU_OGGFLAC |
| 105 |
OggFLAC__StreamEncoderState ogg; |
114 |
OggFLAC__StreamEncoderState ogg; |
| 106 |
#endif |
115 |
#endif |
|
|
116 |
#endif |
| 107 |
} state; |
117 |
} state; |
| 108 |
union { |
118 |
union { |
| 109 |
union { |
119 |
union { |
| 110 |
FLAC__StreamEncoder *stream; |
120 |
FLAC__StreamEncoder *stream; |
|
|
121 |
#ifdef LEGACY_FLAC |
| 111 |
FLAC__SeekableStreamEncoder *s_stream; |
122 |
FLAC__SeekableStreamEncoder *s_stream; |
|
|
123 |
#endif |
| 112 |
} flac; |
124 |
} flac; |
| 113 |
#ifdef AU_OGGFLAC |
125 |
#if defined(LEGACY_FLAC) && defined(AU_OGGFLAC) |
| 114 |
union { |
126 |
union { |
| 115 |
OggFLAC__StreamEncoder *stream; |
127 |
OggFLAC__StreamEncoder *stream; |
| 116 |
} ogg; |
128 |
} ogg; |
|
Lines 158-164
Link Here
|
| 158 |
static long serial_number = 0; |
170 |
static long serial_number = 0; |
| 159 |
FLAC_ctx *flac_ctx = NULL; |
171 |
FLAC_ctx *flac_ctx = NULL; |
| 160 |
|
172 |
|
| 161 |
#ifdef AU_OGGFLAC |
173 |
#if defined(LEGACY_FLAC) && defined(AU_OGGFLAC) |
| 162 |
static FLAC__StreamEncoderWriteStatus |
174 |
static FLAC__StreamEncoderWriteStatus |
| 163 |
ogg_stream_encoder_write_callback(const OggFLAC__StreamEncoder *encoder, |
175 |
ogg_stream_encoder_write_callback(const OggFLAC__StreamEncoder *encoder, |
| 164 |
const FLAC__byte buffer[], |
176 |
const FLAC__byte buffer[], |
|
Lines 168-175
Link Here
|
| 168 |
static FLAC__StreamEncoderWriteStatus |
180 |
static FLAC__StreamEncoderWriteStatus |
| 169 |
flac_stream_encoder_write_callback(const FLAC__StreamEncoder *encoder, |
181 |
flac_stream_encoder_write_callback(const FLAC__StreamEncoder *encoder, |
| 170 |
const FLAC__byte buffer[], |
182 |
const FLAC__byte buffer[], |
|
|
183 |
#ifdef LEGACY_FLAC |
| 171 |
unsigned bytes, unsigned samples, |
184 |
unsigned bytes, unsigned samples, |
|
|
185 |
#else |
| 186 |
size_t bytes, unsigned samples, |
| 187 |
#endif |
| 172 |
unsigned current_frame, void *client_data); |
188 |
unsigned current_frame, void *client_data); |
|
|
189 |
#ifdef LEGACY_FLAC |
| 173 |
static void flac_stream_encoder_metadata_callback(const FLAC__StreamEncoder *encoder, |
190 |
static void flac_stream_encoder_metadata_callback(const FLAC__StreamEncoder *encoder, |
| 174 |
const FLAC__StreamMetadata *metadata, |
191 |
const FLAC__StreamMetadata *metadata, |
| 175 |
void *client_data); |
192 |
void *client_data); |
|
Lines 181-186
Link Here
|
| 181 |
static void flac_seekable_stream_encoder_metadata_callback(const FLAC__SeekableStreamEncoder *encoder, |
198 |
static void flac_seekable_stream_encoder_metadata_callback(const FLAC__SeekableStreamEncoder *encoder, |
| 182 |
const FLAC__StreamMetadata *metadata, |
199 |
const FLAC__StreamMetadata *metadata, |
| 183 |
void *client_data); |
200 |
void *client_data); |
|
|
201 |
#endif |
| 184 |
|
202 |
|
| 185 |
/* preset */ |
203 |
/* preset */ |
| 186 |
void flac_set_compression_level(int compression_level) |
204 |
void flac_set_compression_level(int compression_level) |
|
Lines 281-287
Link Here
|
| 281 |
#ifdef AU_OGGFLAC |
299 |
#ifdef AU_OGGFLAC |
| 282 |
void flac_set_option_oggflac(int isogg) |
300 |
void flac_set_option_oggflac(int isogg) |
| 283 |
{ |
301 |
{ |
|
|
302 |
#ifdef LEGACY_FLAC |
| 284 |
flac_options.isogg = isogg; |
303 |
flac_options.isogg = isogg; |
|
|
304 |
#else |
| 305 |
flac_options.isogg = (FLAC_API_SUPPORTS_OGG_FLAC && isogg); |
| 306 |
#endif |
| 285 |
} |
307 |
} |
| 286 |
#endif |
308 |
#endif |
| 287 |
|
309 |
|
|
Lines 295-300
Link Here
|
| 295 |
dpm.fd = -1; |
317 |
dpm.fd = -1; |
| 296 |
|
318 |
|
| 297 |
if (ctx != NULL) { |
319 |
if (ctx != NULL) { |
|
|
320 |
#ifdef LEGACY_FLAC |
| 298 |
#ifdef AU_OGGFLAC |
321 |
#ifdef AU_OGGFLAC |
| 299 |
if (flac_options.isogg) { |
322 |
if (flac_options.isogg) { |
| 300 |
if (ctx->encoder.ogg.stream) { |
323 |
if (ctx->encoder.ogg.stream) { |
|
Lines 317-322
Link Here
|
| 317 |
FLAC__stream_encoder_delete(ctx->encoder.flac.stream); |
340 |
FLAC__stream_encoder_delete(ctx->encoder.flac.stream); |
| 318 |
} |
341 |
} |
| 319 |
} |
342 |
} |
|
|
343 |
#else |
| 344 |
if (ctx->encoder.flac.stream) { |
| 345 |
FLAC__stream_encoder_finish(ctx->encoder.flac.stream); |
| 346 |
FLAC__stream_encoder_delete(ctx->encoder.flac.stream); |
| 347 |
} |
| 348 |
#endif |
| 320 |
free(ctx); |
349 |
free(ctx); |
| 321 |
flac_ctx = NULL; |
350 |
flac_ctx = NULL; |
| 322 |
} |
351 |
} |
|
Lines 329-334
Link Here
|
| 329 |
FLAC__StreamMetadata padding; |
358 |
FLAC__StreamMetadata padding; |
| 330 |
FLAC__StreamMetadata *metadata[4]; |
359 |
FLAC__StreamMetadata *metadata[4]; |
| 331 |
int num_metadata = 0; |
360 |
int num_metadata = 0; |
|
|
361 |
#ifndef LEGACY_FLAC |
| 362 |
FLAC__StreamEncoderInitStatus init_status; |
| 363 |
#endif |
| 332 |
|
364 |
|
| 333 |
FLAC_ctx *ctx; |
365 |
FLAC_ctx *ctx; |
| 334 |
|
366 |
|
|
Lines 371-376
Link Here
|
| 371 |
metadata[num_metadata++] = &padding; |
403 |
metadata[num_metadata++] = &padding; |
| 372 |
} |
404 |
} |
| 373 |
|
405 |
|
|
|
406 |
#ifdef LEGACY_FLAC |
| 374 |
#ifdef AU_OGGFLAC |
407 |
#ifdef AU_OGGFLAC |
| 375 |
if (flac_options.isogg) { |
408 |
if (flac_options.isogg) { |
| 376 |
if ((ctx->encoder.ogg.stream = OggFLAC__stream_encoder_new()) == NULL) { |
409 |
if ((ctx->encoder.ogg.stream = OggFLAC__stream_encoder_new()) == NULL) { |
|
Lines 542-547
Link Here
|
| 542 |
return -1; |
575 |
return -1; |
| 543 |
} |
576 |
} |
| 544 |
} |
577 |
} |
|
|
578 |
#else /* !LEGACY_FLAC */ |
| 579 |
if ((ctx->encoder.flac.stream = FLAC__stream_encoder_new()) == NULL) { |
| 580 |
ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "cannot create FLAC stream"); |
| 581 |
flac_session_close(); |
| 582 |
return -1; |
| 583 |
} |
| 584 |
|
| 585 |
#ifdef AU_OGGFLAC |
| 586 |
if (flac_options.isogg) { |
| 587 |
/* set sequential number for serial */ |
| 588 |
serial_number++; |
| 589 |
if (serial_number == 1) { |
| 590 |
srand(time(NULL)); |
| 591 |
serial_number = rand(); |
| 592 |
} |
| 593 |
FLAC__stream_encoder_set_ogg_serial_number(ctx->encoder.flac.stream, serial_number); |
| 594 |
} |
| 595 |
#endif /* AU_OGGFLAC */ |
| 596 |
FLAC__stream_encoder_set_channels(ctx->encoder.flac.stream, nch); |
| 597 |
/* 16bps only */ |
| 598 |
FLAC__stream_encoder_set_bits_per_sample(ctx->encoder.flac.stream, 16); |
| 599 |
|
| 600 |
FLAC__stream_encoder_set_verify(ctx->encoder.flac.stream, flac_options.verify); |
| 601 |
|
| 602 |
if (!FLAC__format_sample_rate_is_valid(dpm.rate)) { |
| 603 |
ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "invalid sampling rate %d", dpm.rate); |
| 604 |
flac_session_close(); |
| 605 |
return -1; |
| 606 |
} |
| 607 |
FLAC__stream_encoder_set_sample_rate(ctx->encoder.flac.stream, dpm.rate); |
| 608 |
|
| 609 |
FLAC__stream_encoder_set_qlp_coeff_precision(ctx->encoder.flac.stream, flac_options.qlp_coeff_precision); |
| 610 |
/* expensive! */ |
| 611 |
FLAC__stream_encoder_set_do_qlp_coeff_prec_search(ctx->encoder.flac.stream, flac_options.qlp_coeff_precision_search); |
| 612 |
|
| 613 |
if (nch == 2) { |
| 614 |
FLAC__stream_encoder_set_do_mid_side_stereo(ctx->encoder.flac.stream, flac_options.mid_side); |
| 615 |
FLAC__stream_encoder_set_loose_mid_side_stereo(ctx->encoder.flac.stream, flac_options.adaptive_mid_side); |
| 616 |
} |
| 617 |
|
| 618 |
FLAC__stream_encoder_set_max_lpc_order(ctx->encoder.flac.stream, flac_options.max_lpc_order); |
| 619 |
FLAC__stream_encoder_set_min_residual_partition_order(ctx->encoder.flac.stream, flac_options.min_residual_partition_order); |
| 620 |
FLAC__stream_encoder_set_max_residual_partition_order(ctx->encoder.flac.stream, flac_options.max_residual_partition_order); |
| 621 |
|
| 622 |
FLAC__stream_encoder_set_blocksize(ctx->encoder.flac.stream, flac_options.blocksize); |
| 623 |
|
| 624 |
if (0 < num_metadata) |
| 625 |
FLAC__stream_encoder_set_metadata(ctx->encoder.flac.stream, metadata, num_metadata); |
| 626 |
|
| 627 |
#ifdef AU_OGGFLAC |
| 628 |
if (flac_options.isogg) |
| 629 |
init_status = FLAC__stream_encoder_init_ogg_stream(ctx->encoder.flac.stream, NULL, flac_stream_encoder_write_callback, NULL, NULL, NULL, ctx); |
| 630 |
else |
| 631 |
#endif |
| 632 |
init_status = FLAC__stream_encoder_init_stream(ctx->encoder.flac.stream, flac_stream_encoder_write_callback, NULL, NULL, NULL, ctx); |
| 633 |
if (init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) { |
| 634 |
ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "cannot create FLAC encoder (init status: %s)", FLAC__StreamEncoderInitStatusString[init_status]); |
| 635 |
flac_session_close(); |
| 636 |
return -1; |
| 637 |
} |
| 638 |
#endif |
| 545 |
|
639 |
|
| 546 |
return 0; |
640 |
return 0; |
| 547 |
} |
641 |
} |
|
Lines 638-644
Link Here
|
| 638 |
return 0; |
732 |
return 0; |
| 639 |
} |
733 |
} |
| 640 |
|
734 |
|
| 641 |
#ifdef AU_OGGFLAC |
735 |
#if defined(LEGACY_FLAC) && defined(AU_OGGFLAC) |
| 642 |
static FLAC__StreamEncoderWriteStatus |
736 |
static FLAC__StreamEncoderWriteStatus |
| 643 |
ogg_stream_encoder_write_callback(const OggFLAC__StreamEncoder *encoder, |
737 |
ogg_stream_encoder_write_callback(const OggFLAC__StreamEncoder *encoder, |
| 644 |
const FLAC__byte buffer[], |
738 |
const FLAC__byte buffer[], |
|
Lines 658-664
Link Here
|
| 658 |
static FLAC__StreamEncoderWriteStatus |
752 |
static FLAC__StreamEncoderWriteStatus |
| 659 |
flac_stream_encoder_write_callback(const FLAC__StreamEncoder *encoder, |
753 |
flac_stream_encoder_write_callback(const FLAC__StreamEncoder *encoder, |
| 660 |
const FLAC__byte buffer[], |
754 |
const FLAC__byte buffer[], |
|
|
755 |
#ifdef LEGACY_FLAC |
| 661 |
unsigned bytes, unsigned samples, |
756 |
unsigned bytes, unsigned samples, |
|
|
757 |
#else |
| 758 |
size_t bytes, unsigned samples, |
| 759 |
#endif |
| 662 |
unsigned current_frame, void *client_data) |
760 |
unsigned current_frame, void *client_data) |
| 663 |
{ |
761 |
{ |
| 664 |
FLAC_ctx *ctx = (FLAC_ctx *)client_data; |
762 |
FLAC_ctx *ctx = (FLAC_ctx *)client_data; |
|
Lines 670-675
Link Here
|
| 670 |
else |
768 |
else |
| 671 |
return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR; |
769 |
return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR; |
| 672 |
} |
770 |
} |
|
|
771 |
#ifdef LEGACY_FLAC |
| 673 |
static void flac_stream_encoder_metadata_callback(const FLAC__StreamEncoder *encoder, |
772 |
static void flac_stream_encoder_metadata_callback(const FLAC__StreamEncoder *encoder, |
| 674 |
const FLAC__StreamMetadata *metadata, |
773 |
const FLAC__StreamMetadata *metadata, |
| 675 |
void *client_data) |
774 |
void *client_data) |
|
Lines 695-700
Link Here
|
| 695 |
void *client_data) |
794 |
void *client_data) |
| 696 |
{ |
795 |
{ |
| 697 |
} |
796 |
} |
|
|
797 |
#endif |
| 698 |
|
798 |
|
| 699 |
static int output_data(char *buf, int32 nbytes) |
799 |
static int output_data(char *buf, int32 nbytes) |
| 700 |
{ |
800 |
{ |
|
Lines 723-728
Link Here
|
| 723 |
oggbuf[i] = *s++; |
823 |
oggbuf[i] = *s++; |
| 724 |
} |
824 |
} |
| 725 |
|
825 |
|
|
|
826 |
#ifdef LEGACY_FLAC |
| 726 |
#ifdef AU_OGGFLAC |
827 |
#ifdef AU_OGGFLAC |
| 727 |
if (flac_options.isogg) { |
828 |
if (flac_options.isogg) { |
| 728 |
ctx->state.ogg = OggFLAC__stream_encoder_get_state(ctx->encoder.ogg.stream); |
829 |
ctx->state.ogg = OggFLAC__stream_encoder_get_state(ctx->encoder.ogg.stream); |
|
Lines 793-798
Link Here
|
| 793 |
return -1; |
894 |
return -1; |
| 794 |
} |
895 |
} |
| 795 |
} |
896 |
} |
|
|
897 |
#else /* !LEGACY_FLAC */ |
| 898 |
ctx->state.flac = FLAC__stream_encoder_get_state(ctx->encoder.flac.stream); |
| 899 |
if (ctx->state.flac != FLAC__STREAM_ENCODER_OK) { |
| 900 |
if (ctx->state.flac == FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR | |
| 901 |
FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA) { |
| 902 |
ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "FLAC stream verify error (%s)", |
| 903 |
FLAC__StreamDecoderStateString[FLAC__stream_encoder_get_verify_decoder_state(ctx->encoder.flac.stream)]); |
| 904 |
} |
| 905 |
else { |
| 906 |
ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "cannot encode FLAC stream (%s)", |
| 907 |
FLAC__StreamEncoderStateString[ctx->state.flac]); |
| 908 |
} |
| 909 |
flac_session_close(); |
| 910 |
return -1; |
| 911 |
} |
| 912 |
|
| 913 |
if (!FLAC__stream_encoder_process_interleaved(ctx->encoder.flac.stream, oggbuf, |
| 914 |
nbytes / nch / 2 )) { |
| 915 |
ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "cannot encode FLAC stream"); |
| 916 |
flac_session_close(); |
| 917 |
return -1; |
| 918 |
} |
| 919 |
#endif |
| 796 |
ctx->in_bytes += nbytes; |
920 |
ctx->in_bytes += nbytes; |
| 797 |
|
921 |
|
| 798 |
free(oggbuf); |
922 |
free(oggbuf); |
|
Lines 813-818
Link Here
|
| 813 |
return; |
937 |
return; |
| 814 |
} |
938 |
} |
| 815 |
|
939 |
|
|
|
940 |
#ifdef LEGACY_FLAC |
| 816 |
if (flac_options.isogg) { |
941 |
if (flac_options.isogg) { |
| 817 |
#ifdef AU_OGGFLAC |
942 |
#ifdef AU_OGGFLAC |
| 818 |
if ((ctx->state.ogg = OggFLAC__stream_encoder_get_state(ctx->encoder.ogg.stream)) != OggFLAC__STREAM_ENCODER_OK) { |
943 |
if ((ctx->state.ogg = OggFLAC__stream_encoder_get_state(ctx->encoder.ogg.stream)) != OggFLAC__STREAM_ENCODER_OK) { |
|
Lines 838-843
Link Here
|
| 838 |
/* fall through */ |
963 |
/* fall through */ |
| 839 |
} |
964 |
} |
| 840 |
} |
965 |
} |
|
|
966 |
#else /* !LEGACY_FLAC */ |
| 967 |
if ((ctx->state.flac = FLAC__stream_encoder_get_state(ctx->encoder.flac.stream)) != FLAC__STREAM_ENCODER_OK) { |
| 968 |
ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "FLAC stream encoder is invalid (%s)", |
| 969 |
FLAC__StreamEncoderStateString[ctx->state.flac]); |
| 970 |
/* fall through */ |
| 971 |
} |
| 972 |
#endif |
| 841 |
|
973 |
|
| 842 |
ctl->cmsg(CMSG_INFO, VERB_NORMAL, "Wrote %lu/%lu bytes(%g%% compressed)", |
974 |
ctl->cmsg(CMSG_INFO, VERB_NORMAL, "Wrote %lu/%lu bytes(%g%% compressed)", |
| 843 |
ctx->out_bytes, ctx->in_bytes, ((double)ctx->out_bytes / (double)ctx->in_bytes) * 100.); |
975 |
ctx->out_bytes, ctx->in_bytes, ((double)ctx->out_bytes / (double)ctx->in_bytes) * 100.); |