summaryrefslogtreecommitdiffstats
path: root/debian/transcode/transcode-1.1.7/libtcaudio/tcaudio.c
diff options
context:
space:
mode:
Diffstat (limited to 'debian/transcode/transcode-1.1.7/libtcaudio/tcaudio.c')
-rw-r--r--debian/transcode/transcode-1.1.7/libtcaudio/tcaudio.c439
1 files changed, 439 insertions, 0 deletions
diff --git a/debian/transcode/transcode-1.1.7/libtcaudio/tcaudio.c b/debian/transcode/transcode-1.1.7/libtcaudio/tcaudio.c
new file mode 100644
index 00000000..cb242f45
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/libtcaudio/tcaudio.c
@@ -0,0 +1,439 @@
+/*
+ * tcaudio.c - audio processing library for transcode
+ * Written by Andrew Church <achurch@achurch.org>
+ *
+ * This file is part of transcode, a video stream processing tool.
+ * transcode is free software, distributable under the terms of the GNU
+ * General Public License (version 2 or later). See the file COPYING
+ * for details.
+ */
+
+#include "tcaudio.h"
+
+#include "src/transcode.h"
+#include <math.h>
+
+/*************************************************************************/
+
+/* Internal data structure to hold various state information. The
+ * TCAHandle returned by tca_init() and passed by the caller to other
+ * functions is a pointer to this structure. */
+
+struct tcahandle_ {
+ AudioFormat format; /* Sample format */
+ int bits, issigned, msbfirst; /* Information about sample format */
+};
+
+/*************************************************************************/
+
+/* Internal-use functions (defined at the bottom of the file). */
+
+static int tca_get_format_info(AudioFormat format, int *bits_ret,
+ int *issigned_ret, int *msbfirst_ret);
+static int tca_convert(const char *funcname, TCAHandle handle, void *buf,
+ int len, AudioFormat srcfmt, AudioFormat destfmt);
+
+/*************************************************************************/
+/*************************************************************************/
+
+/* External interface functions. */
+
+/*************************************************************************/
+
+/**
+ * tca_init: Create and return a handle for use in other tcaudio
+ * functions. The handle should be freed with tca_free() when no longer
+ * needed.
+ *
+ * Parameters: format: Audio sample format to use with tcaudio functions.
+ * Return value: A handle to be passed to other tcaudio functions, or 0 on
+ * error.
+ * Preconditions: None.
+ * Postconditions: None.
+ */
+
+TCAHandle tca_init(AudioFormat format)
+{
+ TCAHandle handle;
+ int bits, issigned, msbfirst;
+
+ if (!tca_get_format_info(format, &bits, &issigned, &msbfirst)) {
+ tc_log_error("libtcaudio", "tca_init: invalid audio format (%d)!",
+ format);
+ return NULL;
+ }
+ handle = malloc(sizeof(*handle));
+ if (!handle)
+ return NULL;
+ handle->format = format;
+ handle->bits = bits;
+ handle->issigned = issigned;
+ handle->msbfirst = msbfirst;
+ return handle;
+}
+
+/*************************************************************************/
+
+/**
+ * tca_free: Free resources allocated for the given handle.
+ *
+ * Parameters: handle: tcaudio handle.
+ * Return value: None.
+ * Preconditions: handle != 0: handle was returned by tca_init()
+ * Postconditions: None.
+ */
+
+void tca_free(TCAHandle handle)
+{
+ free(handle);
+}
+
+/*************************************************************************/
+
+/**
+ * tca_convert_from: Convert the given audio buffer from another sample
+ * format to the format given in tca_init().
+ *
+ * Parameters: handle: tcaudio handle.
+ * buf: Audio data buffer.
+ * len: Audio data length, in samples.
+ * srcfmt: Format of source audio samples.
+ * Return value: Nonzero on success, zero on error (invalid parameters).
+ * Preconditions: handle != 0: handle was returned by tca_init()
+ * Postconditions: None.
+ */
+
+int tca_convert_from(TCAHandle handle, void *buf, int len, AudioFormat srcfmt)
+{
+ return tca_convert("tca_convert_from", handle, buf, len, srcfmt,
+ handle->format);
+}
+
+/*************************************************************************/
+
+/**
+ * tca_convert_to: Convert the given audio buffer from the format given in
+ * tca_init() to another sample format.
+ *
+ * Parameters: handle: tcaudio handle.
+ * buf: Audio data buffer.
+ * len: Audio data length, in samples.
+ * destfmt: Format to convert audio samples into.
+ * Return value: Nonzero on success, zero on error (invalid parameters).
+ * Preconditions: handle != 0: handle was returned by tca_init()
+ * Postconditions: None.
+ */
+
+int tca_convert_to(TCAHandle handle, void *buf, int len, AudioFormat destfmt)
+{
+ return tca_convert("tca_convert_to", handle, buf, len, handle->format,
+ destfmt);
+}
+
+/*************************************************************************/
+
+/**
+ * tca_amplify: Amplify the given audio buffer by the given scale factor.
+ * When increasing amplitude (scale factor greater than one), samples are
+ * automatically clipped to the sample format's amplitude range; if
+ * `nclip_ret' is not NULL, the number of clipped samples is stored there
+ * (unmodified on error).
+ *
+ * Parameters: handle: tcaudio handle.
+ * buf: Audio data buffer.
+ * len: Audio data length, in samples.
+ * scale: Factor by which to scale audio data.
+ * nclip_ret: Variable to store number of clipped samples in,
+ * or NULL if this value is not required.
+ * Return value: Nonzero on success, zero on error (invalid parameters).
+ * Preconditions: handle != 0: handle was returned by tca_init()
+ * Postconditions: None.
+ */
+
+int tca_amplify(TCAHandle handle, void *buf, int len, double scale,
+ int *nclip_ret)
+{
+ int nclip;
+
+ if (!handle || !buf || len < 0) {
+ tc_log_error("libtcaudio", "tca_amplify: invalid parameters!");
+ return 0;
+ }
+ nclip = 0;
+ if (handle->bits == 8) {
+ uint8_t *ptr = buf;
+ int bias = handle->issigned ? 0 : 0x80;
+ int i;
+ for (i = 0; i < len; i++) {
+ int32_t v = floor(((ptr[i]-bias) * scale) + 0.5);
+ if (v > 0x7F) {
+ v = 0x7F;
+ nclip++;
+ }
+ if (v < -0x80) {
+ v = -0x80;
+ nclip++;
+ }
+ ptr[i] = v;
+ }
+ } else if (handle->bits == 16) {
+ int8_t *ptr1 = buf + (handle->msbfirst ? 0 : 1);
+ uint8_t *ptr2 = buf + (handle->msbfirst ? 1 : 0);
+ int bias = handle->issigned ? 0 : 0x8000;
+ int i;
+ for (i = 0; i < len; i++) {
+ int32_t v =
+ floor((((ptr1[i*2]<<8 | ptr2[i*2]) - bias) * scale) + 0.5);
+ if (v > 0x7FFF) {
+ v = 0x7FFF;
+ nclip++;
+ }
+ if (v < -0x8000) {
+ v = -0x8000;
+ nclip++;
+ }
+ ptr1[i*2] = v >> 8;
+ ptr2[i*2] = v & 0xFF;
+ }
+ } else {
+ tc_log_error("libtcaudio", "tca_amplify: %d-bit samples not supported",
+ handle->bits);
+ return 0;
+ }
+ if (nclip_ret)
+ *nclip_ret = nclip;
+ return 1;
+}
+
+/*************************************************************************/
+
+/**
+ * tca_mono_to_stereo: Convert monaural audio data to stereo by
+ * duplicating the data into both stereo channels.
+ *
+ * Parameters: handle: tcaudio handle.
+ * buf: Audio data buffer.
+ * len: Audio data length, in stereo samples.
+ * Return value: Nonzero on success, zero on error (invalid parameters).
+ * Preconditions: handle != 0: handle was returned by tca_init()
+ * Postconditions: None.
+ */
+
+int tca_mono_to_stereo(TCAHandle handle, void *buf, int len)
+{
+
+ if (!handle || !buf || len < 0) {
+ tc_log_error("libtcaudio", "tca_mono_to_stereo: invalid parameters!");
+ return 0;
+ }
+ /* Be careful--we have to go backwards or we overwrite unconverted data */
+ if (handle->bits == 8) {
+ uint8_t *ptr = buf;
+ int i;
+ for (i = len-1; i >= 0; i--) {
+ ptr[i*2] = ptr[i];
+ ptr[i*2+1] = ptr[i];
+ }
+ } else if (handle->bits == 16) {
+ uint16_t *ptr = buf;
+ int i;
+ for (i = len-1; i >= 0; i--) {
+ ptr[i*2] = ptr[i];
+ ptr[i*2+1] = ptr[i];
+ }
+ } else {
+ tc_log_error("libtcaudio", "tca_mono_to_stereo: %d-bit samples not"
+ " supported", handle->bits);
+ return 0;
+ }
+ return 1;
+}
+
+/*************************************************************************/
+
+/**
+ * tca_stereo_to_mono: Convert stereo audio data to monaural by mixing the
+ * two stereo channels.
+ *
+ * Parameters: handle: tcaudio handle.
+ * buf: Audio data buffer.
+ * len: Audio data length, in stereo samples.
+ * Return value: Nonzero on success, zero on error (invalid parameters).
+ * Preconditions: handle != 0: handle was returned by tca_init()
+ * Postconditions: None.
+ */
+
+int tca_stereo_to_mono(TCAHandle handle, void *buf, int len)
+{
+ if (!handle || !buf || len < 0) {
+ tc_log_error("libtcaudio", "tca_stereo_to_mono: invalid parameters!");
+ return 0;
+ }
+ if (handle->bits == 8) {
+ uint8_t *ptr = buf;
+ int i;
+ for (i = 0; i < len; i++) {
+ ptr[i] = ((int)ptr[i*2] + (int)ptr[i*2+1] + 1) / 2;
+ }
+ } else if (handle->bits == 16) {
+ int8_t *ptr1 = buf + (handle->msbfirst ? 0 : 1);
+ uint8_t *ptr2 = buf + (handle->msbfirst ? 1 : 0);
+ int i;
+ for (i = 0; i < len; i++) {
+ int32_t v = ((ptr1[i*4]<<8 | ptr2[i*4])
+ + (ptr1[i*4+2]<<8 | ptr2[i*4+2])
+ + 1
+ ) / 2;
+ ptr1[i*2] = v >> 8;
+ ptr2[i*2] = v & 0xFF;
+ }
+ } else {
+ tc_log_error("libtcaudio", "tca_stereo_to_mono: %d-bit samples not"
+ " supported", handle->bits);
+ return 0;
+ }
+ return 1;
+}
+
+/*************************************************************************/
+/*************************************************************************/
+
+/* Internal-use helper functions. */
+
+/*************************************************************************/
+
+/**
+ * tca_get_format_info: Return information about the given audio format.
+ *
+ * Parameters: format: Audio format to get information about.
+ * bits_ret: Set to the number of bits in a sample.
+ * issigned_ret: Set to 1 if samples are signed, else 0.
+ * msbfirst_ret: Set to 1 if samples have the most significant
+ * byte stored first, else 0.
+ * Return value: Nonzero if the format is recognized, zero otherwise.
+ * Preconditions: bits_ret != NULL
+ * issigned_ret != NULL
+ * msbfirst_ret != NULL
+ * Postconditions: None.
+ */
+
+static int tca_get_format_info(AudioFormat format, int *bits_ret,
+ int *issigned_ret, int *msbfirst_ret)
+{
+ switch (format) {
+ case TCA_S8:
+ *bits_ret = 8;
+ *issigned_ret = 1;
+ *msbfirst_ret = 0;
+ return 1;
+ case TCA_U8:
+ *bits_ret = 8;
+ *issigned_ret = 0;
+ *msbfirst_ret = 0;
+ return 1;
+ case TCA_S16BE:
+ *bits_ret = 16;
+ *issigned_ret = 1;
+ *msbfirst_ret = 1;
+ return 1;
+ case TCA_S16LE:
+ *bits_ret = 16;
+ *issigned_ret = 1;
+ *msbfirst_ret = 0;
+ return 1;
+ case TCA_U16BE:
+ *bits_ret = 16;
+ *issigned_ret = 0;
+ *msbfirst_ret = 1;
+ return 1;
+ case TCA_U16LE:
+ *bits_ret = 16;
+ *issigned_ret = 0;
+ *msbfirst_ret = 0;
+ return 1;
+ }
+ return 0;
+}
+
+/*************************************************************************/
+
+/**
+ * tca_convert: Convert from one audio sample format to another.
+ * Implements tca_convert_from() and tca_convert_to().
+ *
+ * Parameters: handle: tcaudio handle.
+ * buf: Audio data buffer.
+ * len: Audio data length, in samples.
+ * srcfmt: Format of source audio samples.
+ * destfmt: Format to convert audio samples into.
+ * Return value: Nonzero on success, zero on error (invalid parameters).
+ * Preconditions: handle != 0: handle was returned by tca_init()
+ * Postconditions: None.
+ */
+
+static int tca_convert(const char *funcname, TCAHandle handle, void *buf,
+ int len, AudioFormat srcfmt, AudioFormat destfmt)
+{
+ int src_bits = -1, src_issigned = -1, src_msbfirst = -1,
+ dest_bits = -1, dest_issigned = -1, dest_msbfirst = -1;
+
+ /* Parameter checks */
+ if (!handle || !buf || len < 0
+ || !tca_get_format_info(srcfmt,&src_bits,&src_issigned,&src_msbfirst)
+ || !tca_get_format_info(destfmt,&dest_bits,&dest_issigned,&dest_msbfirst)
+ ) {
+ tc_log_error("libtcaudio", "%s: invalid parameters!", funcname);
+ return 0;
+ }
+
+ /* Convert sample sizes and byte orders */
+ if (src_bits == 8 && dest_bits == 16) {
+ /* 8 bit -> 16 bit */
+ const uint8_t *src8 = buf;
+ uint8_t *dest8 = buf + (dest_msbfirst ? 0 : 1);
+ int i;
+ /* Go backwards so we don't overwrite unconverted data */
+ for (i = len-1; i >= 0; i--)
+ dest8[i*2] = src8[i];
+ } else if (src_bits == 16 && dest_bits == 8) {
+ /* 16 bit -> 8 bit */
+ const uint8_t *src8 = buf + (src_msbfirst ? 0 : 1);
+ uint8_t *dest8 = buf;
+ int i;
+ for (i = 0; i < len; i++)
+ dest8[i] = src8[i*2];
+ } else if (src_msbfirst != dest_msbfirst) {
+ /* 16 bit -> 16 bit, endian swap */
+ uint16_t *buf16 = buf;
+ int i;
+ for (i = 0; i < len; i++)
+ buf16[i] = buf16[i]<<8 | buf16[i]>>8;
+ } else {
+ /* N bit -> N bit, no change */
+ }
+
+ /* Convert signed/unsigned */
+ if (src_issigned != dest_issigned) {
+ int sampsize = dest_bits / 8;
+ uint8_t *buf8 = buf + (dest_msbfirst ? 0 : sampsize - 1);
+ int i;
+ for (i = 0; i < len * sampsize; i += sampsize)
+ buf8[i] ^= 0x80;
+ }
+
+ /* All done */
+ return 1;
+}
+
+/*************************************************************************/
+/*************************************************************************/
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * c-file-offsets: ((case-label . *) (statement-case-intro . *))
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+ */