diff options
Diffstat (limited to 'debian/transcode/transcode-1.1.7/libtcaudio/tcaudio.c')
| -rw-r--r-- | debian/transcode/transcode-1.1.7/libtcaudio/tcaudio.c | 439 |
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: + */ |
