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) { SOX_SAMPLE_LOCALS; 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; }
static size_t mp3_write(sox_format_t * ft, const sox_sample_t *buf, size_t samp) { int nsamples = samp/ft->signal.channels; int bufsize = nsamples * 4; /* backend accept "forced" stereo of 16bit */ uint16_t *buffer = malloc(bufsize); int clips = 0; int idx = 0; int c = 0; int rc; SOX_SAMPLE_LOCALS; if(!buffer) return 0; if(ft->signal.channels == 1) { /* mono */ for(c = 0; c < samp; c++) { /* left channel */ buffer[idx++] = SOX_SAMPLE_TO_SIGNED_16BIT(buf[c], clips); /* right channel */ buffer[idx++] = 0; } } else { /* stereo: we can ignore special meaning of right channel */ for(idx = 0; idx < samp; idx++) { buffer[idx] = SOX_SAMPLE_TO_SIGNED_16BIT(buf[idx], clips); } } sox_fixedpoint_mp3_t *self = (sox_fixedpoint_mp3_t *) ft->priv; rc = fixedlame_encode(self->codec, (void *)buffer, samp); free(buffer); return rc; }
/* * Process up to *isamp samples from ibuf and produce up to *osamp samples * in obuf. Write back the actual numbers of samples to *isamp and *osamp. * Return SOX_SUCCESS or, if error occurs, SOX_EOF. */ static int flow( sox_effect_t* effp, const sox_sample_t* ibuf, sox_sample_t* obuf, size_t* isamp, size_t* osamp) { priv_t* p = (priv_t*)effp->priv; size_t ibuf_pos = 0; size_t ibuf_end = *isamp; size_t obuf_pos = 0; size_t obuf_end = *osamp; size_t end_pos; SOX_SAMPLE_LOCALS; for (;;) { /* Write any processed data in working buffer to the output buffer. */ end_pos = obuf_pos + min(p->buffer_end - p->buffer_opos, obuf_end - obuf_pos); for (; obuf_pos < end_pos; obuf_pos++, p->buffer_opos++) obuf[obuf_pos] = SOX_SIGNED_16BIT_TO_SAMPLE(p->buffer[p->buffer_opos], dummy); if (p->buffer_opos != p->buffer_end) break; /* Output buffer is full and we still have more processed data. */ /* Fill working buffer from input buffer. */ end_pos = ibuf_pos + min(p->buffer_end - p->buffer_ipos, ibuf_end - ibuf_pos); for (; ibuf_pos < end_pos; ibuf_pos++, p->buffer_ipos++) p->buffer[p->buffer_ipos] = SOX_SAMPLE_TO_SIGNED_16BIT(ibuf[ibuf_pos], effp->clips); if (p->buffer_ipos != p->buffer_end) break; /* Working buffer is not full and there is no more input data. */ speex_preprocess_run(p->sps, p->buffer); p->buffer_ipos = 0; p->buffer_opos = 0; } *isamp = ibuf_pos; *osamp = obuf_pos; 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 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; }