📄 pcm.c
字号:
/******************************************************************************* pcm.c libquicktime - A library for reading and writing quicktime/avi/mp4 files. http://libquicktime.sourceforge.net Copyright (C) 2002 Heroine Virtual Ltd. Copyright (C) 2002-2007 Members of the libquicktime project. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA*******************************************************************************/ #include "lqt_private.h"#include "ulaw_tables.h"#include "alaw_tables.h"#define LQT_LIBQUICKTIME#include <quicktime/lqt_codecapi.h>#include <stdlib.h>#include <string.h>#include <math.h>#include "audiocodec.h"#define LOG_DOMAIN "pcm"#ifndef HAVE_LRINT#define lrint(x) ((long int)(x))#endiftypedef enum { FORMAT_INT_16, FORMAT_INT_24, FORMAT_INT_32, FORMAT_FLOAT_32, FORMAT_FLOAT_64, } format_t;typedef struct quicktime_pcm_codec_s { uint8_t * chunk_buffer; uint8_t * chunk_buffer_ptr; int chunk_buffer_size; int chunk_buffer_alloc; int block_align; int sample_buffer_size; int last_chunk_samples; void (*encode)(struct quicktime_pcm_codec_s*, int num_samples, void * input); void (*decode)(struct quicktime_pcm_codec_s*, int num_samples, void ** output); void (*init_encode)(quicktime_t * file, int track); void (*init_decode)(quicktime_t * file, int track); int initialized; /* Encoding parameters for lpcm */ format_t format; int little_endian; } quicktime_pcm_codec_t;/* 8 bit per sample, signedness and endian neutral */static void encode_8(quicktime_pcm_codec_t*codec, int num_samples, void * _input) { memcpy(codec->chunk_buffer_ptr, _input, num_samples); }static void decode_8(quicktime_pcm_codec_t*codec, int num_samples, void ** _output) { uint8_t * output = (uint8_t *)(*_output); memcpy(output, codec->chunk_buffer_ptr, num_samples); codec->chunk_buffer_ptr += num_samples; output += num_samples; *_output = output; }/* 16 bit per sample, without swapping */static void encode_s16(quicktime_pcm_codec_t*codec, int num_samples, void * _input) { memcpy(codec->chunk_buffer_ptr, _input, 2 * num_samples); }static void decode_s16(quicktime_pcm_codec_t*codec, int num_samples, void ** _output) { uint8_t * output = (uint8_t *)(*_output); memcpy(output, codec->chunk_buffer_ptr, 2 * num_samples); codec->chunk_buffer_ptr += 2 * num_samples; output += 2 * num_samples; *_output = output; }/* 16 bit per sample with swapping */static void encode_s16_swap(quicktime_pcm_codec_t*codec, int num_samples, void * _input) { int i; uint8_t * input = (uint8_t*)_input; for(i = 0; i < num_samples; i++) { codec->chunk_buffer_ptr[0] = input[1]; codec->chunk_buffer_ptr[1] = input[0]; codec->chunk_buffer_ptr+=2; input+=2; } }static void decode_s16_swap(quicktime_pcm_codec_t*codec, int num_samples, void ** _output) { int i; uint8_t * output = (uint8_t*)(*_output); for(i = 0; i < num_samples; i++) { output[0] = codec->chunk_buffer_ptr[1]; output[1] = codec->chunk_buffer_ptr[0]; codec->chunk_buffer_ptr+=2; output+=2; } *_output = output; }/* 24 bit per sample (Big Endian) */static void encode_s24_be(quicktime_pcm_codec_t*codec, int num_samples, void * _input) { int i; /* The uint32_t is intentional: Interpreting integers as unsigned has less pitfalls */ uint32_t * input = (uint32_t*)_input; for(i = 0; i < num_samples; i++) { codec->chunk_buffer_ptr[0] = (*input & 0xff000000) >> 24; codec->chunk_buffer_ptr[1] = (*input & 0xff0000) >> 16; codec->chunk_buffer_ptr[2] = (*input & 0xff00) >> 8; codec->chunk_buffer_ptr+=3; input++; } }static void decode_s24_be(quicktime_pcm_codec_t*codec, int num_samples, void ** _output) { int i; /* The uint32_t is intentional: Interpreting integers as unsigned has less pitfalls */ uint32_t * output = (uint32_t*)(*_output); for(i = 0; i < num_samples; i++) { *output = (uint32_t)(codec->chunk_buffer_ptr[0]) << 24; *output |= (uint32_t)(codec->chunk_buffer_ptr[1]) << 16; *output |= (uint32_t)(codec->chunk_buffer_ptr[2]) << 8; codec->chunk_buffer_ptr+=3; output++; } *_output = output; }/* 24 bit per sample (Little Endian) */static void encode_s24_le(quicktime_pcm_codec_t*codec, int num_samples, void * _input) { int i; /* The uint32_t is intentional: Interpreting integers as unsigned has less pitfalls */ uint32_t * input = (uint32_t*)_input; for(i = 0; i < num_samples; i++) { codec->chunk_buffer_ptr[2] = (*input & 0xff000000) >> 24; codec->chunk_buffer_ptr[1] = (*input & 0xff0000) >> 16; codec->chunk_buffer_ptr[0] = (*input & 0xff00) >> 8; codec->chunk_buffer_ptr+=3; input++; } }static void decode_s24_le(quicktime_pcm_codec_t*codec, int num_samples, void ** _output) { int i; /* The uint32_t is intentional: Interpreting integers as unsigned has less pitfalls */ uint32_t * output = (uint32_t*)(*_output); for(i = 0; i < num_samples; i++) { *output = (uint32_t)(codec->chunk_buffer_ptr[2]) << 24; *output |= (uint32_t)(codec->chunk_buffer_ptr[1]) << 16; *output |= (uint32_t)(codec->chunk_buffer_ptr[0]) << 8; codec->chunk_buffer_ptr+=3; output++; } *_output = output; }/* 32 bit per sample, without swapping */static void encode_s32(quicktime_pcm_codec_t*codec, int num_samples, void * _input) { memcpy(codec->chunk_buffer_ptr, _input, 4 * num_samples); }static void decode_s32(quicktime_pcm_codec_t*codec, int num_samples, void ** _output) { uint8_t * output = (uint8_t *)(*_output); memcpy(output, codec->chunk_buffer_ptr, 4 * num_samples); codec->chunk_buffer_ptr += 4 * num_samples; output += 4 * num_samples; *_output = output; }/* 32 bit per sample with swapping */static void encode_s32_swap(quicktime_pcm_codec_t*codec, int num_samples, void * _input) { int i; uint8_t * input = (uint8_t*)_input; for(i = 0; i < num_samples; i++) { codec->chunk_buffer_ptr[0] = input[3]; codec->chunk_buffer_ptr[1] = input[2]; codec->chunk_buffer_ptr[2] = input[1]; codec->chunk_buffer_ptr[3] = input[0]; codec->chunk_buffer_ptr+=4; input+=4; } }static void decode_s32_swap(quicktime_pcm_codec_t*codec, int num_samples, void ** _output) { int i; uint8_t * output = (uint8_t*)(*_output); for(i = 0; i < num_samples; i++) { output[0] = codec->chunk_buffer_ptr[3]; output[1] = codec->chunk_buffer_ptr[2]; output[2] = codec->chunk_buffer_ptr[1]; output[3] = codec->chunk_buffer_ptr[0]; codec->chunk_buffer_ptr+=4; output+=4; } *_output = output; }/* Floating point formats *//* Sample read/write functions, taken from libsndfile */static floatfloat32_be_read (unsigned char *cptr){ int exponent, mantissa, negative ; float fvalue ; negative = cptr [0] & 0x80 ; exponent = ((cptr [0] & 0x7F) << 1) | ((cptr [1] & 0x80) ? 1 : 0) ; mantissa = ((cptr [1] & 0x7F) << 16) | (cptr [2] << 8) | (cptr [3]) ; if (! (exponent || mantissa)) return 0.0 ; mantissa |= 0x800000 ; exponent = exponent ? exponent - 127 : 0 ; fvalue = mantissa ? ((float) mantissa) / ((float) 0x800000) : 0.0 ; if (negative) fvalue *= -1 ; if (exponent > 0) fvalue *= (1 << exponent) ; else if (exponent < 0) fvalue /= (1 << abs (exponent)) ; return fvalue ;} /* float32_be_read */static floatfloat32_le_read (unsigned char *cptr){ int exponent, mantissa, negative ; float fvalue ; negative = cptr [3] & 0x80 ; exponent = ((cptr [3] & 0x7F) << 1) | ((cptr [2] & 0x80) ? 1 : 0) ; mantissa = ((cptr [2] & 0x7F) << 16) | (cptr [1] << 8) | (cptr [0]) ; if (! (exponent || mantissa)) return 0.0 ; mantissa |= 0x800000 ; exponent = exponent ? exponent - 127 : 0 ; fvalue = mantissa ? ((float) mantissa) / ((float) 0x800000) : 0.0 ; if (negative) fvalue *= -1 ; if (exponent > 0) fvalue *= (1 << exponent) ; else if (exponent < 0) fvalue /= (1 << abs (exponent)) ; return fvalue ;} /* float32_le_read */static doubledouble64_be_read (unsigned char *cptr){ int exponent, negative ; double dvalue ; negative = (cptr [0] & 0x80) ? 1 : 0 ; exponent = ((cptr [0] & 0x7F) << 4) | ((cptr [1] >> 4) & 0xF) ; /* Might not have a 64 bit long, so load the mantissa into a double. */ dvalue = (((cptr [1] & 0xF) << 24) | (cptr [2] << 16) | (cptr [3] << 8) | cptr [4]) ; dvalue += ((cptr [5] << 16) | (cptr [6] << 8) | cptr [7]) / ((double) 0x1000000) ; if (exponent == 0 && dvalue == 0.0) return 0.0 ; dvalue += 0x10000000 ; exponent = exponent - 0x3FF ; dvalue = dvalue / ((double) 0x10000000) ; if (negative) dvalue *= -1 ; if (exponent > 0) dvalue *= (1 << exponent) ; else if (exponent < 0) dvalue /= (1 << abs (exponent)) ; return dvalue ;} /* double64_be_read */static doubledouble64_le_read (unsigned char *cptr){ int exponent, negative ; double dvalue ; negative = (cptr [7] & 0x80) ? 1 : 0 ; exponent = ((cptr [7] & 0x7F) << 4) | ((cptr [6] >> 4) & 0xF) ; /* Might not have a 64 bit long, so load the mantissa into a double. */ dvalue = (((cptr [6] & 0xF) << 24) | (cptr [5] << 16) | (cptr [4] << 8) | cptr [3]) ; dvalue += ((cptr [2] << 16) | (cptr [1] << 8) | cptr [0]) / ((double) 0x1000000) ; if (exponent == 0 && dvalue == 0.0) return 0.0 ; dvalue += 0x10000000 ; exponent = exponent - 0x3FF ; dvalue = dvalue / ((double) 0x10000000) ; if (negative) dvalue *= -1 ; if (exponent > 0) dvalue *= (1 << exponent) ; else if (exponent < 0) dvalue /= (1 << abs (exponent)) ; return dvalue ;} /* double64_le_read */static voidfloat32_le_write (float in, unsigned char *out){ int exponent, mantissa, negative = 0 ; memset (out, 0, sizeof (int)) ; if (in == 0.0) return ; if (in < 0.0) { in *= -1.0 ; negative = 1 ; } ; in = frexp (in, &exponent) ; exponent += 126 ; in *= (float) 0x1000000 ; mantissa = (((int) in) & 0x7FFFFF) ; if (negative) out [3] |= 0x80 ; if (exponent & 0x01) out [2] |= 0x80 ; out [0] = mantissa & 0xFF ; out [1] = (mantissa >> 8) & 0xFF ; out [2] |= (mantissa >> 16) & 0x7F ; out [3] |= (exponent >> 1) & 0x7F ; return ;} /* float32_le_write */static voidfloat32_be_write (float in, unsigned char *out){ int exponent, mantissa, negative = 0 ; memset (out, 0, sizeof (int)) ; if (in == 0.0) return ; if (in < 0.0) { in *= -1.0 ; negative = 1 ; } ; in = frexp (in, &exponent) ; exponent += 126 ; in *= (float) 0x1000000 ; mantissa = (((int) in) & 0x7FFFFF) ; if (negative) out [0] |= 0x80 ; if (exponent & 0x01) out [1] |= 0x80 ; out [3] = mantissa & 0xFF ; out [2] = (mantissa >> 8) & 0xFF ; out [1] |= (mantissa >> 16) & 0x7F ; out [0] |= (exponent >> 1) & 0x7F ; return ;} /* float32_be_write */static voiddouble64_be_write (double in, unsigned char *out){ int exponent, mantissa ; memset (out, 0, sizeof (double)) ; if (in == 0.0) return ; if (in < 0.0) { in *= -1.0 ; out [0] |= 0x80 ; } ; in = frexp (in, &exponent) ; exponent += 1022 ; out [0] |= (exponent >> 4) & 0x7F ; out [1] |= (exponent << 4) & 0xF0 ; in *= 0x20000000 ; mantissa = lrint (floor (in)) ; out [1] |= (mantissa >> 24) & 0xF ; out [2] = (mantissa >> 16) & 0xFF ; out [3] = (mantissa >> 8) & 0xFF ; out [4] = mantissa & 0xFF ; in = fmod (in, 1.0) ; in *= 0x1000000 ; mantissa = lrint (floor (in)) ; out [5] = (mantissa >> 16) & 0xFF ; out [6] = (mantissa >> 8) & 0xFF ; out [7] = mantissa & 0xFF ; return ;} /* double64_be_write */static voiddouble64_le_write (double in, unsigned char *out){ int exponent, mantissa ; memset (out, 0, sizeof (double)) ; if (in == 0.0) return ; if (in < 0.0) { in *= -1.0 ; out [7] |= 0x80 ; } ; in = frexp (in, &exponent) ; exponent += 1022 ; out [7] |= (exponent >> 4) & 0x7F ; out [6] |= (exponent << 4) & 0xF0 ; in *= 0x20000000 ; mantissa = lrint (floor (in)) ; out [6] |= (mantissa >> 24) & 0xF ; out [5] = (mantissa >> 16) & 0xFF ; out [4] = (mantissa >> 8) & 0xFF ; out [3] = mantissa & 0xFF ; in = fmod (in, 1.0) ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -