static void set_endiannesses(sox_format_t * ft) { if (ft->encoding.opposite_endian) ft->encoding.reverse_bytes = (ft->handler.flags & SOX_FILE_ENDIAN)? !(ft->handler.flags & SOX_FILE_ENDBIG) != MACHINE_IS_BIGENDIAN : sox_true; else if (ft->encoding.reverse_bytes == sox_option_default) ft->encoding.reverse_bytes = (ft->handler.flags & SOX_FILE_ENDIAN)? !(ft->handler.flags & SOX_FILE_ENDBIG) == MACHINE_IS_BIGENDIAN : sox_false; /* FIXME: Change reports to suitable warnings if trying * to override something that can't be overridden. */ if (ft->handler.flags & SOX_FILE_ENDIAN) { if (ft->encoding.reverse_bytes == (sox_option_t) (!(ft->handler.flags & SOX_FILE_ENDBIG) != MACHINE_IS_BIGENDIAN)) lsx_report("`%s': overriding file-type byte-order", ft->filename); } else if (ft->encoding.reverse_bytes == sox_option_yes) lsx_report("`%s': overriding machine byte-order", ft->filename); if (ft->encoding.reverse_bits == sox_option_default) ft->encoding.reverse_bits = !!(ft->handler.flags & SOX_FILE_BIT_REV); else if (ft->encoding.reverse_bits == !(ft->handler.flags & SOX_FILE_BIT_REV)) lsx_report("`%s': overriding file-type bit-order", ft->filename); if (ft->encoding.reverse_nibbles == sox_option_default) ft->encoding.reverse_nibbles = !!(ft->handler.flags & SOX_FILE_NIB_REV); else if (ft->encoding.reverse_nibbles == !(ft->handler.flags & SOX_FILE_NIB_REV)) lsx_report("`%s': overriding file-type nibble-order", ft->filename); }
static int startread(sox_format_t * ft) { if (!ft->signal.rate) { ft->signal.rate = SOX_DEFAULT_RATE; lsx_report("sample rate not specified; using %g", ft->signal.rate); } ft->signal.precision = ft->encoding.bits_per_sample? ft->encoding.bits_per_sample: SOX_SAMPLE_PRECISION; /* Default number of channels is application-dependent */ return SOX_SUCCESS; }
/* * note! file must be seekable */ static int dvms_write_header(sox_format_t * ft, struct dvms_header *hdr) { unsigned char hdrbuf[DVMS_HEADER_LEN]; unsigned char *pch = hdrbuf; unsigned char *pchs = hdrbuf; int i; unsigned sum; memcpy(pch, hdr->Filename, sizeof(hdr->Filename)); pch += sizeof(hdr->Filename); put16_le(&pch, hdr->Id); put16_le(&pch, hdr->State); put32_le(&pch, (unsigned)hdr->Unixtime); put16_le(&pch, hdr->Usender); put16_le(&pch, hdr->Ureceiver); put32_le(&pch, (unsigned) hdr->Length); put16_le(&pch, hdr->Srate); put16_le(&pch, hdr->Days); put16_le(&pch, hdr->Custom1); put16_le(&pch, hdr->Custom2); memcpy(pch, hdr->Info, sizeof(hdr->Info)); pch += sizeof(hdr->Info); memcpy(pch, hdr->extend, sizeof(hdr->extend)); pch += sizeof(hdr->extend); for(i = sizeof(hdrbuf), sum = 0; i > /*2*/3; i--) /* Deti bug */ sum += *pchs++; hdr->Crc = sum; put16_le(&pch, hdr->Crc); if (lsx_seeki(ft, (off_t)0, SEEK_SET) < 0) { lsx_report("seek failed\n: %s",strerror(errno)); return (SOX_EOF); } if (lsx_writebuf(ft, hdrbuf, sizeof(hdrbuf)) != sizeof(hdrbuf)) { lsx_report("%s",strerror(errno)); return (SOX_EOF); } return (SOX_SUCCESS); }
static int recover(sox_format_t * ft, snd_pcm_t * pcm, int err) { if (err == -EPIPE) lsx_warn("%s-run", ft->mode == 'r'? "over" : "under"); else if (err != -ESTRPIPE) lsx_warn("%s", snd_strerror(err)); else while ((err = snd_pcm_resume(pcm)) == -EAGAIN) { lsx_report("suspended"); sleep(1); /* Wait until the suspend flag is released */ } if (err < 0 && (err = snd_pcm_prepare(pcm)) < 0) lsx_fail_errno(ft, SOX_EPERM, "%s", snd_strerror(err)); return err; }
static int startread(sox_format_t * ft) { char magic_[sizeof(magic[0])]; uint32_t headers_bytes, num_channels, comments_bytes; uint64_t num_samples; double rate; if (lsx_readdw(ft, (uint32_t *)&magic_)) return SOX_EOF; if (memcmp(magic[MACHINE_IS_BIGENDIAN], magic_, sizeof(magic_))) { if (memcmp(magic[MACHINE_IS_LITTLEENDIAN], magic_, sizeof(magic_))) { lsx_fail_errno(ft, SOX_EHDR, "can't find sox file format identifier"); return SOX_EOF; } ft->encoding.reverse_bytes = !ft->encoding.reverse_bytes; lsx_report("file is opposite endian"); } if (lsx_readdw(ft, &headers_bytes) || lsx_readqw(ft, &num_samples) || lsx_readdf(ft, &rate) || lsx_readdw(ft, &num_channels) || lsx_readdw(ft, &comments_bytes)) return SOX_EOF; if (((headers_bytes + 4) & 7) || headers_bytes < FIXED_HDR + comments_bytes || (num_channels > 65535)) /* Reserve top 16 bits */ { lsx_fail_errno(ft, SOX_EHDR, "invalid sox file format header"); return SOX_EOF; } if (comments_bytes) { char * buf = lsx_calloc(1, (size_t)comments_bytes + 1); /* ensure nul-terminated */ if (lsx_readchars(ft, buf, (size_t)comments_bytes) != SOX_SUCCESS) { free(buf); return SOX_EOF; } sox_append_comments(&ft->oob.comments, buf); free(buf); } /* Consume any bytes after the comments and before the start of the audio * block. These may include comment padding up to a multiple of 8 bytes, * and further header information that might be defined in future. */ lsx_seeki(ft, (off_t)(headers_bytes - FIXED_HDR - comments_bytes), SEEK_CUR); return lsx_check_read_params( ft, num_channels, rate, SOX_ENCODING_SIGN2, 32, (off_t)num_samples, sox_true); }
static int startread(sox_format_t * ft) { char magic[4]; float rate; uint32_t channels, ft_encoding; unsigned i, bits_per_sample; sox_encoding_t encoding; uint16_t code, size; if (lsx_readchars(ft, magic, sizeof(magic))) return SOX_EOF; for (i = 0; id[i].desc && memcmp(magic, id[i].str, sizeof(magic)); ++i); if (!id[i].desc) { lsx_fail_errno(ft, SOX_EHDR, "sf: can't find IRCAM identifier"); return SOX_EOF; } lsx_report("found %s identifier", id[i].desc); ft->encoding.reverse_bytes = id[i].reverse_bytes; if (lsx_readf(ft, &rate) || lsx_readdw(ft, &channels) || lsx_readdw(ft, &ft_encoding)) return SOX_EOF; if (!(encoding = sox_enc(ft_encoding, &bits_per_sample))) { lsx_fail_errno(ft, SOX_EFMT, "sf: unsupported encoding %#x)", ft_encoding); return SOX_EOF; } do { if (lsx_readw(ft, &code) || lsx_readw(ft, &size)) return SOX_EOF; if (code == SF_COMMENT) { char * buf = lsx_calloc(1, (size_t)size + 1); /* +1 ensures null-terminated */ if (lsx_readchars(ft, buf, (size_t) size) != SOX_SUCCESS) { free(buf); return SOX_EOF; } sox_append_comments(&ft->oob.comments, buf); free(buf); } else if (lsx_skipbytes(ft, (size_t) size)) return SOX_EOF; } while (code); if (lsx_skipbytes(ft, FIXED_HDR - (size_t)lsx_tell(ft))) return SOX_EOF; return lsx_check_read_params(ft, channels, rate, encoding, bits_per_sample, (uint64_t)0, sox_true); }
static double * lpf(double Fn, double Fc, double tbw, int * num_taps, double att, double * beta, sox_bool round) { if ((Fc /= Fn) <= 0 || Fc >= 1) { *num_taps = 0; return NULL; } att = att? att : 120; *beta = *beta < 0? lsx_kaiser_beta(att) : *beta; if (!*num_taps) { int n = lsx_lpf_num_taps(att, (tbw? tbw / Fn : .05) * .5, 0); *num_taps = range_limit(n, 11, 32767); if (round) *num_taps = 1 + 2 * (int)((int)((*num_taps / 2) * Fc + .5) / Fc + .5); lsx_report("num taps = %i (from %i)", *num_taps, n); } return lsx_make_lpf(*num_taps |= 1, Fc, *beta, 1., sox_false); }
static int dvms_read_header(sox_format_t * ft, struct dvms_header *hdr) { unsigned char hdrbuf[DVMS_HEADER_LEN]; unsigned char *pch = hdrbuf; int i; unsigned sum; if (lsx_readbuf(ft, hdrbuf, sizeof(hdrbuf)) != sizeof(hdrbuf)) { return (SOX_EOF); } for(i = sizeof(hdrbuf), sum = 0; i > /*2*/3; i--) /* Deti bug */ sum += *pch++; pch = hdrbuf; memcpy(hdr->Filename, pch, sizeof(hdr->Filename)); pch += sizeof(hdr->Filename); hdr->Id = get16_le(&pch); hdr->State = get16_le(&pch); hdr->Unixtime = get32_le(&pch); hdr->Usender = get16_le(&pch); hdr->Ureceiver = get16_le(&pch); hdr->Length = get32_le(&pch); hdr->Srate = get16_le(&pch); hdr->Days = get16_le(&pch); hdr->Custom1 = get16_le(&pch); hdr->Custom2 = get16_le(&pch); memcpy(hdr->Info, pch, sizeof(hdr->Info)); pch += sizeof(hdr->Info); memcpy(hdr->extend, pch, sizeof(hdr->extend)); pch += sizeof(hdr->extend); hdr->Crc = get16_le(&pch); if (sum != hdr->Crc) { lsx_report("DVMS header checksum error, read %u, calculated %u", hdr->Crc, sum); return (SOX_EOF); } return (SOX_SUCCESS); }
static void cvsdstartcommon(sox_format_t * ft) { priv_t *p = (priv_t *) ft->priv; p->cvsd_rate = (ft->signal.rate <= 24000) ? 16000 : 32000; ft->signal.rate = 8000; ft->signal.channels = 1; lsx_rawstart(ft, sox_true, sox_false, sox_true, SOX_ENCODING_CVSD, 1); /* * initialize the decoder */ p->com.overload = 0x5; p->com.mla_int = 0; /* * timeconst = (1/e)^(200 / SR) = exp(-200/SR) * SR is the sampling rate */ p->com.mla_tc0 = exp((-200.0)/((float)(p->cvsd_rate))); /* * phase_inc = 32000 / SR */ p->com.phase_inc = 32000 / p->cvsd_rate; /* * initialize bit shift register */ p->bit.shreg = p->bit.cnt = 0; p->bit.mask = 1; /* * count the bytes written */ p->bytes_written = 0; p->com.v_min = 1; p->com.v_max = -1; lsx_report("cvsd: bit rate %dbit/s, bits from %s", p->cvsd_rate, ft->encoding.reverse_bits ? "msb to lsb" : "lsb to msb"); }
/* * Read up to len samples from p->Synth * If needed, read some more MP3 data, decode them and synth them * Place in buf[]. * Return number of samples read. */ static size_t sox_mp3read(sox_format_t * ft, sox_sample_t *buf, size_t len) { priv_t *p = (priv_t *) ft->priv; size_t donow,i,done=0; mad_fixed_t sample; size_t chan; do { size_t x = (p->Synth.pcm.length - p->cursamp)*ft->signal.channels; donow=min(len, x); i=0; while(i<donow){ for(chan=0;chan<ft->signal.channels;chan++){ sample=p->Synth.pcm.samples[chan][p->cursamp]; if (sample < -MAD_F_ONE) sample=-MAD_F_ONE; else if (sample >= MAD_F_ONE) sample=MAD_F_ONE-1; *buf++=(sox_sample_t)(sample<<(32-1-MAD_F_FRACBITS)); i++; } p->cursamp++; }; len-=donow; done+=donow; if (len==0) break; /* check whether input buffer needs a refill */ if (p->Stream.error == MAD_ERROR_BUFLEN) { if (sox_mp3_input(ft) == SOX_EOF) { lsx_debug("sox_mp3_input EOF"); break; } } if (p->mad_frame_decode(&p->Frame,&p->Stream)) { if(MAD_RECOVERABLE(p->Stream.error)) { sox_mp3_inputtag(ft); continue; } else { if (p->Stream.error == MAD_ERROR_BUFLEN) continue; else { lsx_report("unrecoverable frame level error (%s).", p->mad_stream_errorstr(&p->Stream)); break; } } } p->FrameCount++; p->mad_timer_add(&p->Timer,p->Frame.header.duration); p->mad_synth_frame(&p->Synth,&p->Frame); p->cursamp=0; } while(1); return done; }
sox_format_t * sox_open_read( char const * path, sox_signalinfo_t const * signal, sox_encodinginfo_t const * encoding, char const * filetype) { sox_format_t * ft = lsx_calloc(1, sizeof(*ft)); sox_format_handler_t const * handler; char const * const io_types[] = {"file", "pipe", "file URL"}; char const * type = ""; size_t input_bufsiz = sox_globals.input_bufsiz? sox_globals.input_bufsiz : sox_globals.bufsiz; if (filetype) { if (!(handler = sox_find_format(filetype, sox_false))) { lsx_fail("no handler for given file type `%s'", filetype); goto error; } ft->handler = *handler; } if (!(ft->handler.flags & SOX_FILE_NOSTDIO)) { if (!strcmp(path, "-")) { /* Use stdin if the filename is "-" */ if (sox_globals.stdin_in_use_by) { lsx_fail("`-' (stdin) already in use by `%s'", sox_globals.stdin_in_use_by); goto error; } sox_globals.stdin_in_use_by = "audio input"; SET_BINARY_MODE(stdin); ft->fp = stdin; } else { ft->fp = xfopen(path, "rb", &ft->io_type); type = io_types[ft->io_type]; if (ft->fp == NULL) { lsx_fail("can't open input %s `%s': %s", type, path, strerror(errno)); goto error; } } if (setvbuf (ft->fp, NULL, _IOFBF, sizeof(char) * input_bufsiz)) { lsx_fail("Can't set read buffer"); goto error; } ft->seekable = is_seekable(ft); } if (!filetype) { if (ft->seekable) { filetype = auto_detect_format(ft, lsx_find_file_extension(path)); lsx_rewind(ft); } #ifndef NO_REWIND_PIPE else if (!(ft->handler.flags & SOX_FILE_NOSTDIO) && input_bufsiz >= AUTO_DETECT_SIZE) { filetype = auto_detect_format(ft, lsx_find_file_extension(path)); rewind_pipe(ft->fp); ft->tell_off = 0; } #endif if (filetype) { lsx_report("detected file format type `%s'", filetype); if (!(handler = sox_find_format(filetype, sox_false))) { lsx_fail("no handler for detected file type `%s'", filetype); goto error; } } else { if (ft->io_type == lsx_io_pipe) { filetype = "sox"; /* With successful pipe rewind, this isn't useful */ lsx_report("assuming input pipe `%s' has file-type `sox'", path); } else if (!(filetype = lsx_find_file_extension(path))) { lsx_fail("can't determine type of %s `%s'", type, path); goto error; } if (!(handler = sox_find_format(filetype, sox_true))) { lsx_fail("no handler for file extension `%s'", filetype); goto error; } } ft->handler = *handler; if (ft->handler.flags & SOX_FILE_NOSTDIO) { xfclose(ft->fp, ft->io_type); ft->fp = NULL; } } if (!ft->handler.startread && !ft->handler.read) { lsx_fail("file type `%s' isn't readable", filetype); goto error; } ft->mode = 'r'; ft->filetype = lsx_strdup(filetype); ft->filename = lsx_strdup(path); if (signal) ft->signal = *signal; if (encoding) ft->encoding = *encoding; else sox_init_encodinginfo(&ft->encoding); set_endiannesses(ft); if ((ft->handler.flags & SOX_FILE_DEVICE) && !(ft->handler.flags & SOX_FILE_PHONY)) lsx_set_signal_defaults(ft); ft->priv = lsx_calloc(1, ft->handler.priv_size); /* Read and write starters can change their formats. */ if (ft->handler.startread && (*ft->handler.startread)(ft) != SOX_SUCCESS) { lsx_fail("can't open input %s `%s': %s", type, ft->filename, ft->sox_errstr); goto error; } /* Fill in some defaults: */ if (sox_precision(ft->encoding.encoding, ft->encoding.bits_per_sample)) ft->signal.precision = sox_precision(ft->encoding.encoding, ft->encoding.bits_per_sample); if (!(ft->handler.flags & SOX_FILE_PHONY) && !ft->signal.channels) ft->signal.channels = 1; if (sox_checkformat(ft) != SOX_SUCCESS) { lsx_fail("bad input format for %s `%s': %s", type, ft->filename, ft->sox_errstr); goto error; } if (signal) { if (signal->rate && signal->rate != ft->signal.rate) lsx_warn("can't set sample rate %g; using %g", signal->rate, ft->signal.rate); if (signal->channels && signal->channels != ft->signal.channels) lsx_warn("can't set %u channels; using %u", signal->channels, ft->signal.channels); } return ft; error: if (ft->fp && ft->fp != stdin) xfclose(ft->fp, ft->io_type); free(ft->priv); free(ft->filename); free(ft->filetype); free(ft); return NULL; }
static int start_write(sox_format_t * const ft) { priv_t * p = (priv_t *)ft->priv; FLAC__StreamEncoderState status; unsigned compression_level = MAX_COMPRESSION; /* Default to "best" */ if (ft->encoding.compression != HUGE_VAL) { compression_level = ft->encoding.compression; if (compression_level != ft->encoding.compression || compression_level > MAX_COMPRESSION) { lsx_fail_errno(ft, SOX_EINVAL, "FLAC compression level must be a whole number from 0 to %i", MAX_COMPRESSION); return SOX_EOF; } } p->encoder = FLAC__stream_encoder_new(); if (p->encoder == NULL) { lsx_fail_errno(ft, SOX_ENOMEM, "FLAC ERROR creating the encoder instance"); return SOX_EOF; } p->decoded_samples = lsx_malloc(sox_globals.bufsiz * sizeof(FLAC__int32)); p->bits_per_sample = ft->encoding.bits_per_sample; lsx_report("encoding at %i bits per sample", p->bits_per_sample); FLAC__stream_encoder_set_channels(p->encoder, ft->signal.channels); FLAC__stream_encoder_set_bits_per_sample(p->encoder, p->bits_per_sample); FLAC__stream_encoder_set_sample_rate(p->encoder, (unsigned)(ft->signal.rate + .5)); { /* Check if rate is streamable: */ static const unsigned streamable_rates[] = {8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000}; size_t i; sox_bool streamable = sox_false; for (i = 0; !streamable && i < array_length(streamable_rates); ++i) streamable = (streamable_rates[i] == ft->signal.rate); if (!streamable) { lsx_report("non-standard rate; output may not be streamable"); FLAC__stream_encoder_set_streamable_subset(p->encoder, sox_false); } } #if FLAC_API_VERSION_CURRENT >= 10 FLAC__stream_encoder_set_compression_level(p->encoder, compression_level); #else { static struct { unsigned blocksize; FLAC__bool do_exhaustive_model_search; FLAC__bool do_mid_side_stereo; FLAC__bool loose_mid_side_stereo; unsigned max_lpc_order; unsigned max_residual_partition_order; unsigned min_residual_partition_order; } const options[MAX_COMPRESSION + 1] = { {1152, sox_false, sox_false, sox_false, 0, 2, 2}, {1152, sox_false, sox_true, sox_true, 0, 2, 2}, {1152, sox_false, sox_true, sox_false, 0, 3, 0}, {4608, sox_false, sox_false, sox_false, 6, 3, 3}, {4608, sox_false, sox_true, sox_true, 8, 3, 3}, {4608, sox_false, sox_true, sox_false, 8, 3, 3}, {4608, sox_false, sox_true, sox_false, 8, 4, 0}, {4608, sox_true, sox_true, sox_false, 8, 6, 0}, {4608, sox_true, sox_true, sox_false, 12, 6, 0}, }; #define SET_OPTION(x) do {\ lsx_report(#x" = %i", options[compression_level].x); \ FLAC__stream_encoder_set_##x(p->encoder, options[compression_level].x);\ } while (0) SET_OPTION(blocksize); SET_OPTION(do_exhaustive_model_search); SET_OPTION(max_lpc_order); SET_OPTION(max_residual_partition_order); SET_OPTION(min_residual_partition_order); if (ft->signal.channels == 2) { SET_OPTION(do_mid_side_stereo); SET_OPTION(loose_mid_side_stereo); } #undef SET_OPTION } #endif if (ft->signal.length != 0) { FLAC__stream_encoder_set_total_samples_estimate(p->encoder, (FLAC__uint64)(ft->signal.length / ft->signal.channels)); p->metadata[p->num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_SEEKTABLE); if (p->metadata[p->num_metadata] == NULL) { lsx_fail_errno(ft, SOX_ENOMEM, "FLAC ERROR creating the encoder seek table template"); return SOX_EOF; } { #if FLAC_API_VERSION_CURRENT >= 8 if (!FLAC__metadata_object_seektable_template_append_spaced_points_by_samples(p->metadata[p->num_metadata], (unsigned)(10 * ft->signal.rate + .5), (FLAC__uint64)(ft->signal.length/ft->signal.channels))) { #else size_t samples = 10 * ft->signal.rate; size_t total_samples = ft->signal.length/ft->signal.channels; if (!FLAC__metadata_object_seektable_template_append_spaced_points(p->metadata[p->num_metadata], total_samples / samples + (total_samples % samples != 0), (FLAC__uint64)total_samples)) { #endif lsx_fail_errno(ft, SOX_ENOMEM, "FLAC ERROR creating the encoder seek table points"); return SOX_EOF; } } p->metadata[p->num_metadata]->is_last = sox_false; /* the encoder will set this for us */ ++p->num_metadata; } if (ft->oob.comments) { /* Make the comment structure */ FLAC__StreamMetadata_VorbisComment_Entry entry; int i; p->metadata[p->num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT); for (i = 0; ft->oob.comments[i]; ++i) { static const char prepend[] = "Comment="; char * text = lsx_calloc(strlen(prepend) + strlen(ft->oob.comments[i]) + 1, sizeof(*text)); /* Prepend `Comment=' if no field-name already in the comment */ if (!strchr(ft->oob.comments[i], '=')) strcpy(text, prepend); entry.entry = (FLAC__byte *) strcat(text, ft->oob.comments[i]); entry.length = strlen(text); FLAC__metadata_object_vorbiscomment_append_comment(p->metadata[p->num_metadata], entry, /*copy= */ sox_true); free(text); } ++p->num_metadata; } if (p->num_metadata) FLAC__stream_encoder_set_metadata(p->encoder, p->metadata, p->num_metadata); #if FLAC_API_VERSION_CURRENT <= 7 FLAC__stream_encoder_set_write_callback(p->encoder, flac_stream_encoder_write_callback); FLAC__stream_encoder_set_metadata_callback(p->encoder, flac_stream_encoder_metadata_callback); FLAC__stream_encoder_set_client_data(p->encoder, ft); status = FLAC__stream_encoder_init(p->encoder); #else status = FLAC__stream_encoder_init_stream(p->encoder, flac_stream_encoder_write_callback, flac_stream_encoder_seek_callback, flac_stream_encoder_tell_callback, flac_stream_encoder_metadata_callback, ft); #endif if (status != FLAC__STREAM_ENCODER_OK) { lsx_fail_errno(ft, SOX_EINVAL, "%s", FLAC__StreamEncoderStateString[status]); return SOX_EOF; } return SOX_SUCCESS; } static size_t write_samples(sox_format_t * const ft, sox_sample_t const * const sampleBuffer, size_t const len) { priv_t * p = (priv_t *)ft->priv; unsigned i; for (i = 0; i < len; ++i) { long pcm = SOX_SAMPLE_TO_SIGNED_32BIT(sampleBuffer[i], ft->clips); p->decoded_samples[i] = pcm >> (32 - p->bits_per_sample); switch (p->bits_per_sample) { case 8: p->decoded_samples[i] = SOX_SAMPLE_TO_SIGNED_8BIT(sampleBuffer[i], ft->clips); break; case 16: p->decoded_samples[i] = SOX_SAMPLE_TO_SIGNED_16BIT(sampleBuffer[i], ft->clips); break; case 24: p->decoded_samples[i] = /* sign extension: */ SOX_SAMPLE_TO_SIGNED_24BIT(sampleBuffer[i],ft->clips) << 8; p->decoded_samples[i] >>= 8; break; case 32: p->decoded_samples[i] = SOX_SAMPLE_TO_SIGNED_32BIT(sampleBuffer[i],ft->clips); break; } } FLAC__stream_encoder_process_interleaved(p->encoder, p->decoded_samples, (unsigned) len / ft->signal.channels); return FLAC__stream_encoder_get_state(p->encoder) == FLAC__STREAM_ENCODER_OK ? len : 0; }
/* common r/w initialization code */ static int ossinit(sox_format_t * ft) { int sampletype, samplesize, dsp_stereo; int tmp, rc; priv_t *file = (priv_t *)ft->priv; if (ft->encoding.bits_per_sample == 8) { sampletype = AFMT_U8; samplesize = 8; if (ft->encoding.encoding == SOX_ENCODING_UNKNOWN) ft->encoding.encoding = SOX_ENCODING_UNSIGNED; if (ft->encoding.encoding != SOX_ENCODING_UNSIGNED) { lsx_report("OSS driver only supports unsigned with bytes"); lsx_report("Forcing to unsigned"); ft->encoding.encoding = SOX_ENCODING_UNSIGNED; } } else if (ft->encoding.bits_per_sample == 16) { /* Attempt to use endian that user specified */ if (ft->encoding.reverse_bytes) sampletype = (MACHINE_IS_BIGENDIAN) ? AFMT_S16_LE : AFMT_S16_BE; else sampletype = (MACHINE_IS_BIGENDIAN) ? AFMT_S16_BE : AFMT_S16_LE; samplesize = 16; if (ft->encoding.encoding == SOX_ENCODING_UNKNOWN) ft->encoding.encoding = SOX_ENCODING_SIGN2; if (ft->encoding.encoding != SOX_ENCODING_SIGN2) { lsx_report("OSS driver only supports signed with words"); lsx_report("Forcing to signed linear"); ft->encoding.encoding = SOX_ENCODING_SIGN2; } } else { /* Attempt to use endian that user specified */ if (ft->encoding.reverse_bytes) sampletype = (MACHINE_IS_BIGENDIAN) ? AFMT_S16_LE : AFMT_S16_BE; else sampletype = (MACHINE_IS_BIGENDIAN) ? AFMT_S16_BE : AFMT_S16_LE; samplesize = 16; ft->encoding.bits_per_sample = 16; ft->encoding.encoding = SOX_ENCODING_SIGN2; lsx_report("OSS driver only supports bytes and words"); lsx_report("Forcing to signed linear word"); } if (ft->signal.channels > 2) ft->signal.channels = 2; if (ioctl(fileno(ft->fp), (size_t) SNDCTL_DSP_RESET, 0) < 0) { lsx_fail_errno(ft,SOX_EOF,"Unable to reset OSS driver. Possibly accessing an invalid file/device"); return(SOX_EOF); } /* Query the supported formats and find the best match */ rc = ioctl(fileno(ft->fp), SNDCTL_DSP_GETFMTS, &tmp); if (rc == 0) { if ((tmp & sampletype) == 0) { /* is 16-bit supported? */ if (samplesize == 16 && (tmp & (AFMT_S16_LE|AFMT_S16_BE)) == 0) { /* Must not like 16-bits, try 8-bits */ ft->encoding.bits_per_sample = 8; ft->encoding.encoding = SOX_ENCODING_UNSIGNED; lsx_report("OSS driver doesn't like signed words"); lsx_report("Forcing to unsigned bytes"); tmp = sampletype = AFMT_U8; samplesize = 8; } /* is 8-bit supported */ else if (samplesize == 8 && (tmp & AFMT_U8) == 0) { ft->encoding.bits_per_sample = 16; ft->encoding.encoding = SOX_ENCODING_SIGN2; lsx_report("OSS driver doesn't like unsigned bytes"); lsx_report("Forcing to signed words"); sampletype = (MACHINE_IS_BIGENDIAN) ? AFMT_S16_BE : AFMT_S16_LE; samplesize = 16; } /* determine which 16-bit format to use */ if (samplesize == 16 && (tmp & sampletype) == 0) { /* Either user requested something not supported * or hardware doesn't support machine endian. * Force to opposite as the above test showed * it supports at least one of the two endians. */ sampletype = (sampletype == AFMT_S16_BE) ? AFMT_S16_LE : AFMT_S16_BE; ft->encoding.reverse_bytes = !ft->encoding.reverse_bytes; } } tmp = sampletype; rc = ioctl(fileno(ft->fp), SNDCTL_DSP_SETFMT, &tmp); } /* Give up and exit */ if (rc < 0 || tmp != sampletype) { lsx_fail_errno(ft,SOX_EOF,"Unable to set the sample size to %d", samplesize); return (SOX_EOF); } if (ft->signal.channels == 2) dsp_stereo = 1; else dsp_stereo = 0; tmp = dsp_stereo; if (ioctl(fileno(ft->fp), SNDCTL_DSP_STEREO, &tmp) < 0) { lsx_warn("Couldn't set to %s", dsp_stereo? "stereo":"mono"); dsp_stereo = 0; } if (tmp != dsp_stereo) ft->signal.channels = tmp + 1; tmp = ft->signal.rate; if (ioctl (fileno(ft->fp), SNDCTL_DSP_SPEED, &tmp) < 0 || (int)ft->signal.rate != tmp) { /* If the rate the sound card is using is not within 1% of what * the user specified then override the user setting. * The only reason not to always override this is because of * clock-rounding problems. Sound cards will sometimes use * things like 44101 when you ask for 44100. No need overriding * this and having strange output file rates for something that * we can't hear anyways. */ if ((int)ft->signal.rate - tmp > (tmp * .01) || tmp - (int)ft->signal.rate > (tmp * .01)) ft->signal.rate = tmp; } /* Find out block size to use last because the driver could compute * its size based on specific rates/formats. */ file->size = 0; ioctl (fileno(ft->fp), SNDCTL_DSP_GETBLKSIZE, &file->size); if (file->size < 4 || file->size > 65536) { lsx_fail_errno(ft,SOX_EOF,"Invalid audio buffer size %lu", (unsigned long)file->size); return (SOX_EOF); } file->count = 0; file->pos = 0; file->buf = lsx_malloc(file->size); if (ioctl(fileno(ft->fp), (size_t) SNDCTL_DSP_SYNC, NULL) < 0) { lsx_fail_errno(ft,SOX_EOF,"Unable to sync dsp"); return (SOX_EOF); } /* Change to non-buffered I/O */ setvbuf(ft->fp, NULL, _IONBF, sizeof(char) * file->size); return(SOX_SUCCESS); }
/* * Process command-line options but don't do other * initialization now: effp->in_signal & effp->out_signal are not * yet filled in. */ static int getopts(sox_effect_t* effp, int argc, char** argv) { priv_t* p = (priv_t*)effp->priv; const size_t agcDefault = 100; const size_t denoiseDefault = 15; const size_t fpsDefault = 50; for (argc--, argv++; argc; argc--, argv++) { if (!strcasecmp("-agc", argv[0])) { /* AGC level argument is optional. If not specified, it defaults to agcDefault. If specified, it must be from 0 to 100. */ if (!get_param(&argc, &argv, &p->agc, agcDefault, 0, 100)) { lsx_fail("Invalid argument \"%s\" to -agc parameter - expected number from 0 to 100.", argv[1]); return lsx_usage(effp); } } else if (!strcasecmp("-denoise", argv[0])) { /* Denoise level argument is optional. If not specified, it defaults to denoiseDefault. If specified, it must be from 0 to 100. */ if (!get_param(&argc, &argv, &p->denoise, denoiseDefault, 0, 100)) { lsx_fail("Invalid argument \"%s\" to -denoise parameter - expected number from 0 to 100.", argv[1]); return lsx_usage(effp); } } else if (!strcasecmp("-dereverb", argv[0])) { p->dereverb = 1; } else if (!strcasecmp("-spf", argv[0])) { /* If samples_per_frame option is given, argument is required and must be greater than 0. */ if (!get_param(&argc, &argv, &p->samples_per_frame, 0, 1, 1000000000) || !p->samples_per_frame) { lsx_fail("Invalid argument \"%s\" to -spf parameter - expected positive number.", argv[1]); return lsx_usage(effp); } } else if (!strcasecmp("-fps", argv[0])) { /* If frames_per_second option is given, argument is required and must be from 1 to 100. This will be used later to compute samples_per_frame once we know the sample rate). */ if (!get_param(&argc, &argv, &p->frames_per_second, 0, 1, 100) || !p->frames_per_second) { lsx_fail("Invalid argument \"%s\" to -fps parameter - expected number from 1 to 100.", argv[1]); return lsx_usage(effp); } } else { lsx_fail("Invalid parameter \"%s\".", argv[0]); return lsx_usage(effp); } } if (!p->frames_per_second) p->frames_per_second = fpsDefault; if (!p->agc && !p->denoise && !p->dereverb) { lsx_report("No features specified. Enabling default settings \"-agc %u -denoise %u\".", agcDefault, denoiseDefault); p->agc = agcDefault; p->denoise = denoiseDefault; } return SOX_SUCCESS; }