static int check_read_params(sox_format_t * ft, unsigned channels, sox_rate_t rate, sox_encoding_t encoding, unsigned bits_per_sample, off_t length) { ft->signal.length = length; if (channels && ft->signal.channels && ft->signal.channels != channels) lsx_warn("`%s': overriding number of channels", ft->filename); else ft->signal.channels = channels; if (rate && ft->signal.rate && ft->signal.rate != rate) lsx_warn("`%s': overriding sample rate", ft->filename); else ft->signal.rate = rate; if (encoding && ft->encoding.encoding && ft->encoding.encoding != encoding) lsx_warn("`%s': overriding encoding type", ft->filename); else ft->encoding.encoding = encoding; if (bits_per_sample && ft->encoding.bits_per_sample && ft->encoding.bits_per_sample != bits_per_sample) lsx_warn("`%s': overriding encoding size", ft->filename); ft->encoding.bits_per_sample = bits_per_sample; if (sox_precision(ft->encoding.encoding, ft->encoding.bits_per_sample)) return SOX_SUCCESS; lsx_fail_errno(ft, EINVAL, "invalid format for this file type"); return SOX_EOF; }
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 void FLAC__decoder_metadata_callback(FLAC__StreamDecoder const * const flac, FLAC__StreamMetadata const * const metadata, void * const client_data) { sox_format_t * ft = (sox_format_t *) client_data; priv_t * p = (priv_t *)ft->priv; (void) flac; if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO) { p->bits_per_sample = metadata->data.stream_info.bits_per_sample; p->channels = metadata->data.stream_info.channels; p->sample_rate = metadata->data.stream_info.sample_rate; p->total_samples = metadata->data.stream_info.total_samples; } else if (metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) { size_t i; if (metadata->data.vorbis_comment.num_comments == 0) return; if (ft->oob.comments != NULL) { lsx_warn("multiple Vorbis comment block ignored"); return; } for (i = 0; i < metadata->data.vorbis_comment.num_comments; ++i) sox_append_comment(&ft->oob.comments, (char const *) metadata->data.vorbis_comment.comments[i].entry); } }
static int stop(sox_effect_t * effp) { priv_t * p = (priv_t *)effp->priv; if (p->pos[0].at || (p->pos[1].at && p->argc == 2)) lsx_warn("input audio was too short to crop as requested"); return SOX_SUCCESS; }
static int select_format( sox_encoding_t * encoding_, unsigned * nbits_, snd_pcm_format_mask_t const * mask, int * format) { unsigned can_do[NSIZES], i, j, index = (*nbits_ >> 3) - 1, nbits; sox_encoding_t encoding = *encoding_; for (i = 0; i < NSIZES; ++i) for (can_do[i] = 0, j = 0; j < 2; ++j) can_do[i] |= snd_pcm_format_mask_test(mask, formats[j][i]); if (index >= NSIZES || (encoding != SOX_ENCODING_SIGN2 && encoding != SOX_ENCODING_UNSIGNED)){ encoding = SOX_ENCODING_SIGN2; index = 2; } while (!can_do[index]) if (++index == NSIZES) /* Search up */ for (--index; !can_do[index];) if (--index >= NSIZES) /* then down */ return -1; nbits = (index + 1) << 3; if (encoding == SOX_ENCODING_SIGN2 && !snd_pcm_format_mask_test(mask, formats[0][index])) encoding = SOX_ENCODING_UNSIGNED; if (*nbits_ != nbits || *encoding_ != encoding) { lsx_warn("can't encode %u-bit %s", *nbits_, sox_encodings_info[*encoding_].desc); *nbits_ = nbits; *encoding_ = encoding; } *format = formats[encoding == SOX_ENCODING_UNSIGNED][index]; return 0; }
static int stop(sox_effect_t * effp) { priv_t * p = (priv_t *)effp->priv; if (p->pads_pos != p->npads) lsx_warn("Input audio too short; pads not applied: %u", p->npads-p->pads_pos); return SOX_SUCCESS; }
static int stop_read(sox_format_t * const ft) { priv_t * p = (priv_t *)ft->priv; if (!FLAC__stream_decoder_finish(p->decoder) && p->eof) lsx_warn("decoder MD5 checksum mismatch."); FLAC__stream_decoder_delete(p->decoder); return SOX_SUCCESS; }
/* * Do anything required when you stop reading samples. * Don't close input file! */ static int sox_dcshift_stop(sox_effect_t * effp) { priv_t * dcs = (priv_t *) effp->priv; if (dcs->limited) { lsx_warn("DCSHIFT limited %" PRIu64 " values (%d percent).", dcs->limited, (int) (dcs->limited * 100.0 / dcs->totalprocessed)); } return SOX_SUCCESS; }
static int startwrite(sox_format_t * ft) { priv_t * sf = (priv_t *)ft->priv; start(ft); /* If output format is invalid, try to find a sensible default */ if (!sf_format_check(sf->sf_info)) { SF_FORMAT_INFO format_info; int i, count; sf_command(sf->sf_file, SFC_GET_SIMPLE_FORMAT_COUNT, &count, (int) sizeof(int)); for (i = 0; i < count; i++) { format_info.format = i; sf_command(sf->sf_file, SFC_GET_SIMPLE_FORMAT, &format_info, (int) sizeof(format_info)); if ((format_info.format & SF_FORMAT_TYPEMASK) == (sf->sf_info->format & SF_FORMAT_TYPEMASK)) { sf->sf_info->format = format_info.format; /* FIXME: Print out exactly what we chose, needs sndfile -> sox encoding conversion functions */ break; } } if (!sf_format_check(sf->sf_info)) { lsx_fail("cannot find a usable output encoding"); return SOX_EOF; } if ((sf->sf_info->format & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW) lsx_warn("cannot use desired output encoding, choosing default"); } sf->sf_file = sf_open_fd(fileno(ft->fp), SFM_WRITE, sf->sf_info, 1); ft->fp = NULL; /* Transfer ownership of fp to LSF */ drain_log_buffer(ft); if (sf->sf_file == NULL) { memset(ft->sox_errstr, 0, sizeof(ft->sox_errstr)); strncpy(ft->sox_errstr, sf_strerror(sf->sf_file), sizeof(ft->sox_errstr)-1); free(sf->sf_file); return SOX_EOF; } #ifdef HAVE_SFC_SET_SCALE_INT_FLOAT_WRITE if ((sf->sf_info->format & SF_FORMAT_SUBMASK) == SF_FORMAT_FLOAT) sf_command(sf->sf_file, SFC_SET_SCALE_INT_FLOAT_WRITE, NULL, SF_TRUE); #endif return SOX_SUCCESS; }
/* * Open file in sndfile. */ static int startread(sox_format_t * ft) { priv_t * sf = (priv_t *)ft->priv; unsigned bits_per_sample; sox_encoding_t encoding; sox_rate_t rate; start(ft); sf->sf_file = sf_open_fd(fileno(ft->fp), SFM_READ, sf->sf_info, 1); ft->fp = NULL; /* Transfer ownership of fp to LSF */ drain_log_buffer(ft); if (sf->sf_file == NULL) { memset(ft->sox_errstr, 0, sizeof(ft->sox_errstr)); strncpy(ft->sox_errstr, sf_strerror(sf->sf_file), sizeof(ft->sox_errstr)-1); free(sf->sf_file); return SOX_EOF; } if (!(encoding = sox_enc(sf->sf_info->format, &bits_per_sample))) { lsx_fail_errno(ft, SOX_EFMT, "unsupported sndfile encoding %#x", sf->sf_info->format); return SOX_EOF; } /* Don't believe LSF's rate for raw files */ if ((sf->sf_info->format & SF_FORMAT_TYPEMASK) == SF_FORMAT_RAW && !ft->signal.rate) { lsx_warn("`%s': sample rate not specified; trying 8kHz", ft->filename); rate = 8000; } else rate = sf->sf_info->samplerate; #ifdef HAVE_SFC_SET_SCALE_FLOAT_INT_READ if ((sf->sf_info->format & SF_FORMAT_SUBMASK) == SF_FORMAT_FLOAT) { sf_command(sf->sf_file, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE); sf_command(sf->sf_file, SFC_SET_CLIPPING, NULL, SF_TRUE); } #endif #if 0 /* FIXME */ sox_append_comments(&ft->oob.comments, buf); #endif return check_read_params(ft, (unsigned)sf->sf_info->channels, rate, encoding, bits_per_sample, (off_t)(sf->sf_info->frames * sf->sf_info->channels)); }
int lsx_dvmsstartwrite(sox_format_t * ft) { struct dvms_header hdr; int rc; rc = lsx_cvsdstartwrite(ft); if (rc) return rc; make_dvms_hdr(ft, &hdr); rc = dvms_write_header(ft, &hdr); if (rc){ lsx_fail_errno(ft,rc,"cannot write DVMS header"); return rc; } if (!ft->seekable) lsx_warn("Length in output .DVMS header will wrong since can't seek to fix it"); return(SOX_SUCCESS); }
/* * Drain LSF's wonderful log buffer */ static void drain_log_buffer(sox_format_t * ft) { priv_t * sf = (priv_t *)ft->priv; sf_command(sf->sf_file, SFC_GET_LOG_INFO, sf->log_buffer, LOG_MAX); while (*sf->log_buffer_ptr) { static char const warning_prefix[] = "*** Warning : "; char const * end = strchr(sf->log_buffer_ptr, '\n'); if (!end) end = strchr(sf->log_buffer_ptr, '\0'); if (!strncmp(sf->log_buffer_ptr, warning_prefix, strlen(warning_prefix))) { sf->log_buffer_ptr += strlen(warning_prefix); lsx_warn("`%s': %.*s", ft->filename, (int)(end - sf->log_buffer_ptr), sf->log_buffer_ptr); } else lsx_debug("`%s': %.*s", ft->filename, (int)(end - sf->log_buffer_ptr), sf->log_buffer_ptr); sf->log_buffer_ptr = end; if (*sf->log_buffer_ptr == '\n') ++sf->log_buffer_ptr; } }
/* * Start processing */ static int sox_trim_start(sox_effect_t * effp) { priv_t * trim = (priv_t *) effp->priv; if (lsx_parsesamples(effp->in_signal.rate, trim->start_str, &trim->start, 't') == NULL) return lsx_usage(effp); if (trim->end_str) { if (lsx_parsesamples(effp->in_signal.rate, trim->end_str, &trim->length, 't') == NULL) return lsx_usage(effp); if (trim->end_is_absolute) { if (trim->length < trim->start) { lsx_warn("end earlier than start"); trim->length = 0; /* with trim->end_str != NULL, this really means zero */ } else trim->length -= trim->start; } } else trim->length = 0; /* with trim->end_str == NULL, this means indefinite length */ lsx_debug("start at %lus, length %lu", trim->start, trim->length); /* Account for # of channels */ trim->start *= effp->in_signal.channels; trim->length *= effp->in_signal.channels; trim->index = 0; trim->trimmed = 0; effp->out_signal.length = trim->length; return (SOX_SUCCESS); }
/* * Drain out remaining samples if the effect generates any. */ static int sox_fade_drain(sox_effect_t * effp, sox_sample_t *obuf, size_t *osamp) { priv_t * fade = (priv_t *) effp->priv; int len; size_t t_chan = 0; len = *osamp; len -= len % effp->in_signal.channels; *osamp = 0; if (fade->do_out && fade->samplesdone < fade->out_stop && !(fade->endpadwarned)) { /* Warning about padding silence into end of sample */ lsx_warn("End time past end of audio. Padding with silence"); fade->endpadwarned = 1; } /* endif endpadwarned */ for (;len && (fade->do_out && fade->samplesdone < fade->out_stop); len--) { *obuf = 0; obuf++; *osamp += 1; t_chan++; if (t_chan >= effp->in_signal.channels) { fade->samplesdone += 1; t_chan = 0; } /* endif channels */ } /* endfor */ if (fade->do_out && fade->samplesdone >= fade->out_stop) return SOX_EOF; else return SOX_SUCCESS; }
int lsx_dvmsstopwrite(sox_format_t * ft) { struct dvms_header hdr; int rc; lsx_cvsdstopwrite(ft); if (!ft->seekable) { lsx_warn("File not seekable"); return (SOX_EOF); } if (lsx_seeki(ft, (off_t)0, 0) != 0) { lsx_fail_errno(ft,errno,"Can't rewind output file to rewrite DVMS header."); return(SOX_EOF); } make_dvms_hdr(ft, &hdr); rc = dvms_write_header(ft, &hdr); if(rc){ lsx_fail_errno(ft,rc,"cannot write DVMS header"); return rc; } return rc; }
static int sox_mp3seek(sox_format_t * ft, uint64_t offset) { priv_t * p = (priv_t *) ft->priv; size_t initial_bitrate = p->Frame.header.bitrate; size_t tagsize = 0, consumed = 0; sox_bool vbr = sox_false; /* Variable Bit Rate */ sox_bool depadded = sox_false; uint64_t to_skip_samples = 0; /* Reset all */ rewind((FILE*)ft->fp); mad_timer_reset(&p->Timer); p->FrameCount = 0; /* They where opened in startread */ mad_synth_finish(&p->Synth); p->mad_frame_finish(&p->Frame); p->mad_stream_finish(&p->Stream); p->mad_stream_init(&p->Stream); p->mad_frame_init(&p->Frame); p->mad_synth_init(&p->Synth); offset /= ft->signal.channels; to_skip_samples = offset; while(sox_true) { /* Read data from the MP3 file */ int read, padding = 0; size_t leftover = p->Stream.bufend - p->Stream.next_frame; memcpy(p->mp3_buffer, p->Stream.this_frame, leftover); read = fread(p->mp3_buffer + leftover, (size_t) 1, p->mp3_buffer_size - leftover, (FILE*)ft->fp); if (read <= 0) { lsx_debug("seek failure. unexpected EOF (frames=%" PRIuPTR " leftover=%" PRIuPTR ")", p->FrameCount, leftover); break; } for (; !depadded && padding < read && !p->mp3_buffer[padding]; ++padding); depadded = sox_true; p->mad_stream_buffer(&p->Stream, p->mp3_buffer + padding, leftover + read - padding); while (sox_true) { /* Decode frame headers */ static unsigned short samples; p->Stream.error = MAD_ERROR_NONE; /* Not an audio frame */ if (p->mad_header_decode(&p->Frame.header, &p->Stream) == -1) { if (p->Stream.error == MAD_ERROR_BUFLEN) break; /* Normal behaviour; get some more data from the file */ if (!MAD_RECOVERABLE(p->Stream.error)) { lsx_warn("unrecoverable MAD error"); break; } if (p->Stream.error == MAD_ERROR_LOSTSYNC) { unsigned available = (p->Stream.bufend - p->Stream.this_frame); tagsize = tagtype(p->Stream.this_frame, (size_t) available); if (tagsize) { /* It's some ID3 tags, so just skip */ if (tagsize >= available) { fseeko((FILE*)ft->fp, (off_t)(tagsize - available), SEEK_CUR); depadded = sox_false; } p->mad_stream_skip(&p->Stream, min(tagsize, available)); } else lsx_warn("MAD lost sync"); } else lsx_warn("recoverable MAD error"); continue; } consumed += p->Stream.next_frame - p->Stream.this_frame; vbr |= (p->Frame.header.bitrate != initial_bitrate); samples = 32 * MAD_NSBSAMPLES(&p->Frame.header); p->FrameCount++; p->mad_timer_add(&p->Timer, p->Frame.header.duration); if(to_skip_samples <= samples) { p->mad_frame_decode(&p->Frame,&p->Stream); p->mad_synth_frame(&p->Synth, &p->Frame); p->cursamp = to_skip_samples; return SOX_SUCCESS; } else to_skip_samples -= samples; /* If not VBR, we can extrapolate frame size */ if (p->FrameCount == 64 && !vbr) { p->FrameCount = offset / samples; to_skip_samples = offset % samples; if (SOX_SUCCESS != lsx_seeki(ft, (off_t)(p->FrameCount * consumed / 64 + tagsize), SEEK_SET)) return SOX_EOF; /* Reset Stream for refilling buffer */ p->mad_stream_finish(&p->Stream); p->mad_stream_init(&p->Stream); break; } } }; return SOX_EOF; }
/* 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); }
/* * Prepare for processing. */ static int sox_echo_start(sox_effect_t * effp) { priv_t * echo = (priv_t *) effp->priv; int i; float sum_in_volume; long j; echo->maxsamples = 0; if ( echo->in_gain < 0.0 ) { lsx_fail("echo: gain-in must be positive!"); return (SOX_EOF); } if ( echo->in_gain > 1.0 ) { lsx_fail("echo: gain-in must be less than 1.0!"); return (SOX_EOF); } if ( echo->out_gain < 0.0 ) { lsx_fail("echo: gain-in must be positive!"); return (SOX_EOF); } for ( i = 0; i < echo->num_delays; i++ ) { echo->samples[i] = echo->delay[i] * effp->in_signal.rate / 1000.0; if ( echo->samples[i] < 1 ) { lsx_fail("echo: delay must be positive!"); return (SOX_EOF); } if ( echo->samples[i] > (ptrdiff_t)DELAY_BUFSIZ ) { lsx_fail("echo: delay must be less than %g seconds!", DELAY_BUFSIZ / effp->in_signal.rate ); return (SOX_EOF); } if ( echo->decay[i] < 0.0 ) { lsx_fail("echo: decay must be positive!" ); return (SOX_EOF); } if ( echo->decay[i] > 1.0 ) { lsx_fail("echo: decay must be less than 1.0!" ); return (SOX_EOF); } if ( echo->samples[i] > echo->maxsamples ) echo->maxsamples = echo->samples[i]; } echo->delay_buf = lsx_malloc(sizeof (double) * echo->maxsamples); for ( j = 0; j < echo->maxsamples; ++j ) echo->delay_buf[j] = 0.0; /* Be nice and check the hint with warning, if... */ sum_in_volume = 1.0; for ( i = 0; i < echo->num_delays; i++ ) sum_in_volume += echo->decay[i]; if ( sum_in_volume * echo->in_gain > 1.0 / echo->out_gain ) lsx_warn("echo: warning >>> gain-out can cause saturation of output <<<"); echo->counter = 0; echo->fade_out = echo->maxsamples; effp->out_signal.length = SOX_UNKNOWN_LEN; /* TODO: calculate actual length */ return (SOX_SUCCESS); }
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; }
/* * Start processing */ static int sox_pan_start(sox_effect_t * effp) { if (effp->out_signal.channels==1) lsx_warn("PAN onto a mono channel..."); return SOX_SUCCESS; }
/*----------------------------------------------------------------- * read() -- read data from a VOC file * ANN: Major changes here to support multi-part files and files * that do not have audio in block 9's. *-----------------------------------------------------------------*/ static size_t read_samples(sox_format_t * ft, sox_sample_t * buf, size_t len) { priv_t * v = (priv_t *) ft->priv; size_t done = 0; int rc = 0; int16_t sw; unsigned char uc; if (v->block_remaining == 0) { /* handle getting another cont. buffer */ rc = getblock(ft); if (rc) return 0; } if (v->block_remaining == 0) /* if no more data, return 0, i.e., done */ return 0; if (v->silent) { for (; v->block_remaining && (done < len); v->block_remaining--, done++) *buf++ = 0; /* Fill in silence */ } else { /* not silence; read len samples of audio from the file */ size_t per = max(1, 9 / v->size); for (; (done + per <= len); done += per) { if (v->block_remaining == 0) { /* IF no more in this block, get another */ while (v->block_remaining == 0) { /* until have either EOF or a block with data */ rc = getblock(ft); if (rc) break; } if (rc) /* IF EOF, break out, no more data, next will return 0 */ break; } /* Read the data in the file */ if (v->size <= 4) { if (!v->adpcm.setup.sign) { SOX_SAMPLE_LOCALS; if (lsx_readb(ft, &uc) == SOX_EOF) { lsx_warn("VOC input: short file"); v->block_remaining = 0; return done; } *buf = SOX_UNSIGNED_8BIT_TO_SAMPLE(uc,); lsx_adpcm_init(&v->adpcm, 6 - v->size, SOX_SAMPLE_TO_SIGNED_16BIT(*buf, ft->clips)); ++buf; --v->block_remaining; ++done; } if (lsx_readb(ft, &uc) == SOX_EOF) { lsx_warn("VOC input: short file"); v->block_remaining = 0; return done; } switch (v->size) { case 2: if (v->format == VOC_FMT_CRLADPCM2) { int u = uc; *buf++ = SOX_SIGNED_16BIT_TO_SAMPLE(lsx_adpcm_decode (u >> 6, &v->adpcm),); *buf++ = SOX_SIGNED_16BIT_TO_SAMPLE(lsx_adpcm_decode (u >> 4, &v->adpcm),); *buf++ = SOX_SIGNED_16BIT_TO_SAMPLE(lsx_adpcm_decode (u >> 2, &v->adpcm),); *buf++ = SOX_SIGNED_16BIT_TO_SAMPLE(lsx_adpcm_decode (u , &v->adpcm),); } break; case 3: if (v->format == VOC_FMT_CRLADPCM3) { int u = uc; *buf++ = SOX_SIGNED_16BIT_TO_SAMPLE(lsx_adpcm_decode (u >> 5, &v->adpcm),); *buf++ = SOX_SIGNED_16BIT_TO_SAMPLE(lsx_adpcm_decode (u >> 2, &v->adpcm),); *buf++ = /* A bit from nowhere! */ SOX_SIGNED_16BIT_TO_SAMPLE(lsx_adpcm_decode (u << 1, &v->adpcm),); } break; case 4: if (v->format == VOC_FMT_CRLADPCM4) { int u = uc; *buf++ = SOX_SIGNED_16BIT_TO_SAMPLE(lsx_adpcm_decode (u >> 4, &v->adpcm),); *buf++ = SOX_SIGNED_16BIT_TO_SAMPLE(lsx_adpcm_decode (u , &v->adpcm),); } break; }
static void _fixedlame_logf(const char *msg) { lsx_warn(msg); }
static int stop(sox_effect_t * effp) { priv_t * p = (priv_t *)effp->priv; if (!effp->flow) { double min_runs = 0, max_count = 0, min = 2, max = -2, max_sigma_x = 0, sigma_x = 0, sigma_x2 = 0, min_sigma_x2 = 2, max_sigma_x2 = 0, avg_peak = 0; off_t num_samples = 0, min_count = 0, max_runs = 0; uint32_t mask = 0; unsigned b1, b2, i, n = effp->flows > 1 ? effp->flows : 0; for (i = 0; i < effp->flows; ++i) { priv_t * q = (priv_t *)(effp - effp->flow + i)->priv; min = min(min, q->min); max = max(max, q->max); min_sigma_x2 = min(min_sigma_x2, q->min_sigma_x2); max_sigma_x2 = max(max_sigma_x2, q->max_sigma_x2); sigma_x += q->sigma_x; sigma_x2 += q->sigma_x2; num_samples += q->num_samples; mask |= q->mask; if (fabs(q->sigma_x) > fabs(max_sigma_x)) max_sigma_x = q->sigma_x; min_count += q->min_count; min_runs += q->min_runs; max_count += q->max_count; max_runs += q->max_runs; avg_peak += max(-q->min, q->max); } avg_peak /= effp->flows; if (!num_samples) { lsx_warn("no audio"); return SOX_SUCCESS; } if (n == 2) fprintf(stderr, " Overall Left Right\n"); else if (n) { fprintf(stderr, " Overall"); for (i = 0; i < n; ++i) fprintf(stderr, " Ch%-3i", i + 1); fprintf(stderr, "\n"); } fprintf(stderr, "DC offset "); output(p, max_sigma_x / p->num_samples); for (i = 0; i < n; ++i) { priv_t * q = (priv_t *)(effp - effp->flow + i)->priv; output(p, q->sigma_x / q->num_samples); } fprintf(stderr, "\nMin level "); output(p, min); for (i = 0; i < n; ++i) { priv_t * q = (priv_t *)(effp - effp->flow + i)->priv; output(p, q->min); } fprintf(stderr, "\nMax level "); output(p, max); for (i = 0; i < n; ++i) { priv_t * q = (priv_t *)(effp - effp->flow + i)->priv; output(p, q->max); } fprintf(stderr, "\nPk lev dB %10.2f", linear_to_dB(max(-min, max))); for (i = 0; i < n; ++i) { priv_t * q = (priv_t *)(effp - effp->flow + i)->priv; fprintf(stderr, "%10.2f", linear_to_dB(max(-q->min, q->max))); } fprintf(stderr, "\nRMS lev dB%10.2f", linear_to_dB(sqrt(sigma_x2 / num_samples))); for (i = 0; i < n; ++i) { priv_t * q = (priv_t *)(effp - effp->flow + i)->priv; fprintf(stderr, "%10.2f", linear_to_dB(sqrt(q->sigma_x2 / q->num_samples))); } fprintf(stderr, "\nRMS Pk dB %10.2f", linear_to_dB(sqrt(max_sigma_x2))); for (i = 0; i < n; ++i) { priv_t * q = (priv_t *)(effp - effp->flow + i)->priv; fprintf(stderr, "%10.2f", linear_to_dB(sqrt(q->max_sigma_x2))); } fprintf(stderr, "\nRMS Tr dB "); if (min_sigma_x2 != 1) fprintf(stderr, "%10.2f", linear_to_dB(sqrt(min_sigma_x2))); else fprintf(stderr, " -"); for (i = 0; i < n; ++i) { priv_t * q = (priv_t *)(effp - effp->flow + i)->priv; if (q->min_sigma_x2 != 1) fprintf(stderr, "%10.2f", linear_to_dB(sqrt(q->min_sigma_x2))); else fprintf(stderr, " -"); } if (effp->flows > 1) fprintf(stderr, "\nCrest factor -"); else fprintf(stderr, "\nCrest factor %7.2f", sigma_x2 ? avg_peak / sqrt(sigma_x2 / num_samples) : 1); for (i = 0; i < n; ++i) { priv_t * q = (priv_t *)(effp - effp->flow + i)->priv; fprintf(stderr, "%10.2f", q->sigma_x2? max(-q->min, q->max) / sqrt(q->sigma_x2 / q->num_samples) : 1); } fprintf(stderr, "\nFlat factor%9.2f", linear_to_dB((min_runs + max_runs) / (min_count + max_count))); for (i = 0; i < n; ++i) { priv_t * q = (priv_t *)(effp - effp->flow + i)->priv; fprintf(stderr, " %9.2f", linear_to_dB((q->min_runs + q->max_runs) / (q->min_count + q->max_count))); } fprintf(stderr, "\nPk count %9s", lsx_sigfigs3((min_count + max_count) / effp->flows)); for (i = 0; i < n; ++i) { priv_t * q = (priv_t *)(effp - effp->flow + i)->priv; fprintf(stderr, " %9s", lsx_sigfigs3((double)(q->min_count + q->max_count))); } b1 = bit_depth(mask, min, max, &b2); fprintf(stderr, "\nBit-depth %2u/%-2u", b1, b2); for (i = 0; i < n; ++i) { priv_t * q = (priv_t *)(effp - effp->flow + i)->priv; b1 = bit_depth(q->mask, q->min, q->max, &b2); fprintf(stderr, " %2u/%-2u", b1, b2); } fprintf(stderr, "\nNum samples%9s", lsx_sigfigs3((double)p->num_samples)); fprintf(stderr, "\nLength s %9.3f", p->num_samples / effp->in_signal.rate); fprintf(stderr, "\nScale max "); output(p, 1.); fprintf(stderr, "\nWindow s %9.3f", p->time_constant); fprintf(stderr, "\n"); } return SOX_SUCCESS; }