📄 pcm.c
字号:
in *= 0x1000000 ; mantissa = lrint (floor (in)) ; out [2] = (mantissa >> 16) & 0xFF ; out [1] = (mantissa >> 8) & 0xFF ; out [0] = mantissa & 0xFF ; return ;} /* double64_le_write *//* 32 bit float (Big Endian) */static void encode_fl32_be(quicktime_pcm_codec_t*codec, int num_samples, void * _input) { int i; float * input = (float*)_input; for(i = 0; i < num_samples; i++) { float32_be_write(*input, codec->chunk_buffer_ptr); codec->chunk_buffer_ptr+=4; input++; } }static void decode_fl32_be(quicktime_pcm_codec_t*codec, int num_samples, void ** _output) { int i; float * output = (float*)(*_output); for(i = 0; i < num_samples; i++) { *output = float32_be_read(codec->chunk_buffer_ptr); codec->chunk_buffer_ptr+=4; output++; } *_output = output; }/* 32 bit float (Little Endian) */static void encode_fl32_le(quicktime_pcm_codec_t*codec, int num_samples, void * _input) { int i; float * input = (float*)_input; for(i = 0; i < num_samples; i++) { float32_le_write(*input, codec->chunk_buffer_ptr); codec->chunk_buffer_ptr+=4; input++; } }static void decode_fl32_le(quicktime_pcm_codec_t*codec, int num_samples, void ** _output) { int i; float * output = (float*)(*_output); for(i = 0; i < num_samples; i++) { *output = float32_le_read(codec->chunk_buffer_ptr); codec->chunk_buffer_ptr+=4; output++; } *_output = output; }/* 64 bit float (Big Endian) */static void encode_fl64_be(quicktime_pcm_codec_t*codec, int num_samples, void * _input) { int i; double * input = (double*)_input; for(i = 0; i < num_samples; i++) { double64_be_write(*input, codec->chunk_buffer_ptr); codec->chunk_buffer_ptr+=8; input++; } }static void decode_fl64_be(quicktime_pcm_codec_t*codec, int num_samples, void ** _output) { int i; double * output = (double*)(*_output); for(i = 0; i < num_samples; i++) { *output = double64_be_read(codec->chunk_buffer_ptr); codec->chunk_buffer_ptr+=8; output++; } *_output = output; }/* 64 bit float (Little Endian) */static void encode_fl64_le(quicktime_pcm_codec_t*codec, int num_samples, void * _input) { int i; double * input = (double*)_input; for(i = 0; i < num_samples; i++) { double64_le_write(*input, codec->chunk_buffer_ptr); codec->chunk_buffer_ptr+=8; input++; } }static void decode_fl64_le(quicktime_pcm_codec_t*codec, int num_samples, void ** _output) { int i; double * output = (double*)(*_output); for(i = 0; i < num_samples; i++) { *output = double64_le_read(codec->chunk_buffer_ptr); codec->chunk_buffer_ptr+=8; output++; } *_output = output; }/* ulaw *//* See ulaw_tables.h for the tables references here */#define ENCODE_ULAW(src, dst) if(src >= 0) dst = ulaw_encode[src / 4]; else dst = 0x7F & ulaw_encode[src / -4] #define DECODE_ULAW(src, dst) dst = ulaw_decode [src]static void encode_ulaw(quicktime_pcm_codec_t*codec, int num_samples, void * _input) { int i; int16_t * input = (int16_t*)_input; for(i = 0; i < num_samples; i++) { ENCODE_ULAW(input[0], codec->chunk_buffer_ptr[0]); codec->chunk_buffer_ptr++; input++; } }static void decode_ulaw(quicktime_pcm_codec_t*codec, int num_samples, void ** _output) { int i; /* The uint32_t is intentional: Interpreting integers as unsigned has less pitfalls */ int16_t * output = (int16_t*)(*_output); for(i = 0; i < num_samples; i++) { DECODE_ULAW(codec->chunk_buffer_ptr[0], output[0]); codec->chunk_buffer_ptr++; output++; } *_output = output; }/* alaw *//* See alaw_tables.h for the tables references here */#define ENCODE_ALAW(src, dst) if(src >= 0) dst = alaw_encode[src / 16]; else dst = 0x7F & alaw_encode[src / -16] #define DECODE_ALAW(src, dst) dst = alaw_decode [src]static void encode_alaw(quicktime_pcm_codec_t*codec, int num_samples, void * _input) { int i; int16_t * input = (int16_t*)_input; for(i = 0; i < num_samples; i++) { ENCODE_ALAW(input[0], codec->chunk_buffer_ptr[0]); codec->chunk_buffer_ptr++; input++; } }static void decode_alaw(quicktime_pcm_codec_t*codec, int num_samples, void ** _output) { int i; /* The uint32_t is intentional: Interpreting integers as unsigned has less pitfalls */ int16_t * output = (int16_t*)(*_output); for(i = 0; i < num_samples; i++) { DECODE_ALAW(codec->chunk_buffer_ptr[0], output[0]); codec->chunk_buffer_ptr++; output++; } *_output = output; }/* Generic decode function */static int read_audio_chunk(quicktime_t * file, int track, long chunk, uint8_t ** buffer, int * buffer_alloc) { int bytes, samples, bytes_from_samples; quicktime_audio_map_t *track_map = &(file->atracks[track]); quicktime_pcm_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv; bytes = lqt_read_audio_chunk(file, track, chunk, buffer, buffer_alloc, &samples); bytes_from_samples = samples * codec->block_align; if(bytes > bytes_from_samples) return bytes_from_samples; else return bytes; }static int decode_pcm(quicktime_t *file, void * _output, long samples, int track) { int64_t chunk, chunk_sample; quicktime_audio_map_t *track_map = &(file->atracks[track]); quicktime_pcm_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv; void * output; int64_t samples_to_skip = 0; int samples_in_chunk; int samples_decoded, samples_to_decode; if(!codec->initialized) { if(codec->init_decode) codec->init_decode(file, track); /* Read the first audio chunk */ codec->chunk_buffer_size = read_audio_chunk(file, track, file->atracks[track].current_chunk, &(codec->chunk_buffer), &(codec->chunk_buffer_alloc)); if(codec->chunk_buffer_size <= 0) { lqt_log(file, LQT_LOG_ERROR, LOG_DOMAIN, "EOF at the beginning of track"); return 0; } codec->chunk_buffer_ptr = codec->chunk_buffer; codec->initialized = 1; } if(!_output) /* Global initialization */ { return 0; } if(file->atracks[track].current_position != file->atracks[track].last_position) { /* Seeking happened */ quicktime_chunk_of_sample(&chunk_sample, &chunk, file->atracks[track].track, file->atracks[track].current_position); /* Read the chunk */ if(file->atracks[track].current_chunk != chunk) { file->atracks[track].current_chunk = chunk; codec->chunk_buffer_size = read_audio_chunk(file, track, file->atracks[track].current_chunk, &(codec->chunk_buffer), &(codec->chunk_buffer_alloc)); if(codec->chunk_buffer_size <= 0) return 0; codec->chunk_buffer_ptr = codec->chunk_buffer; } else { codec->chunk_buffer_ptr = codec->chunk_buffer; } /* Skip samples */ samples_to_skip = file->atracks[track].current_position - chunk_sample; if(samples_to_skip < 0) { lqt_log(file, LQT_LOG_ERROR, LOG_DOMAIN, "Cannot skip backwards"); samples_to_skip = 0; } codec->chunk_buffer_ptr = codec->chunk_buffer + samples_to_skip * codec->block_align; } samples_decoded = 0; output = _output; while(samples_decoded < samples) { /* Get new chunk if necessary */ if(codec->chunk_buffer_ptr - codec->chunk_buffer >= codec->chunk_buffer_size) { file->atracks[track].current_chunk++; codec->chunk_buffer_size = read_audio_chunk(file, track, file->atracks[track].current_chunk, &(codec->chunk_buffer), &(codec->chunk_buffer_alloc)); if(codec->chunk_buffer_size <= 0) break; codec->chunk_buffer_ptr = codec->chunk_buffer; } /* Decode */ samples_in_chunk = ((codec->chunk_buffer_size-(int)(codec->chunk_buffer_ptr - codec->chunk_buffer))) /codec->block_align; samples_to_decode = samples - samples_decoded; if(samples_to_decode > samples_in_chunk) samples_to_decode = samples_in_chunk; codec->decode(codec, samples_to_decode * track_map->channels, &output); samples_decoded += samples_to_decode; } file->atracks[track].last_position = file->atracks[track].current_position + samples_decoded; return samples_decoded; }/* Generic encode function */static int encode_pcm(quicktime_t *file, void * input, long samples, int track) { int result; quicktime_atom_t chunk_atom; quicktime_audio_map_t *track_map = &(file->atracks[track]); quicktime_pcm_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv; quicktime_trak_t *trak = track_map->track; /* Initialize */ if(!codec->initialized) { /* Initialize AVI header */ if(trak->strl) { /* strh stuff */ trak->strl->strh.dwRate = track_map->samplerate; trak->strl->strh.dwScale = 1; trak->strl->strh.dwSampleSize = codec->block_align / track_map->channels; /* WAVEFORMATEX stuff */ trak->strl->strf.wf.f.WAVEFORMAT.nBlockAlign = codec->block_align; trak->strl->strf.wf.f.WAVEFORMAT.nAvgBytesPerSec = codec->block_align * track_map->samplerate; trak->strl->strf.wf.f.PCMWAVEFORMAT.wBitsPerSample = trak->strl->strh.dwSampleSize * 8; } if(codec->init_encode) codec->init_encode(file, track); codec->initialized = 1; } if(!input || !samples) return 0; /* Allocate chunk buffer */ if(codec->chunk_buffer_alloc < samples * codec->block_align) { codec->chunk_buffer_alloc = samples * codec->block_align + 1024; codec->chunk_buffer = realloc(codec->chunk_buffer, codec->chunk_buffer_alloc); } codec->chunk_buffer_ptr = codec->chunk_buffer; codec->encode(codec, samples * track_map->channels, input); quicktime_write_chunk_header(file, trak, &chunk_atom); result = quicktime_write_data(file, codec->chunk_buffer, samples * codec->block_align); quicktime_write_chunk_footer(file, trak, track_map->current_chunk, &chunk_atom, samples); file->atracks[track].current_chunk++; /* defeat fwrite's return */ if(result) result = 0; else result = 1; return result; }/* Set parameters */static int set_parameter_pcm(quicktime_t *file, int track, const char *key, const void *value) { quicktime_audio_map_t *atrack = &(file->atracks[track]); quicktime_pcm_codec_t *codec = ((quicktime_codec_t*)atrack->codec)->priv; if(!strcasecmp(key, "pcm_little_endian")) { codec->little_endian = *((int*)(value)); } else if(!strcasecmp(key, "pcm_format")) { if(!strcasecmp((char*)(value), "Integer (16 bit)")) codec->format = FORMAT_INT_16; else if(!strcasecmp((char*)(value), "Integer (24 bit)")) codec->format = FORMAT_INT_24; else if(!strcasecmp((char*)(value), "Integer (32 bit)")) codec->format = FORMAT_INT_32; else if(!strcasecmp((char*)(value), "Float (32 bit)")) codec->format = FORMAT_FLOAT_32; else if(!strcasecmp((char*)(value), "Float (64 bit)")) codec->format = FORMAT_FLOAT_64; } return 0; }/* Destructor */static int delete_pcm(quicktime_audio_map_t *atrack) { quicktime_pcm_codec_t *codec = ((quicktime_codec_t*)atrack->codec)->priv; if(codec->chunk_buffer) { free(codec->chunk_buffer); } free(codec); return 0; }void quicktime_init_codec_twos(quicktime_audio_map_t *atrack) { quicktime_pcm_codec_t *codec; quicktime_codec_t *codec_base = (quicktime_codec_t*)atrack->codec; /* Init public items */ codec_base->delete_acodec = delete_pcm; codec_base->decode_audio = decode_pcm; codec_base->encode_audio = encode_pcm; /* Init private items */ codec = calloc(1, sizeof(*codec)); codec_base->priv = codec; switch(atrack->track->mdia.minf.stbl.stsd.table[0].sample_size) { case 8: codec->block_align = atrack->channels; atrack->sample_format = LQT_SAMPLE_INT8; codec->encode = encode_8; codec->decode = decode_8; break; case 16: codec->block_align = 2 * atrack->channels; atrack->sample_format = LQT_SAMPLE_INT16;#ifdef WORDS_BIGENDIAN codec->encode = encode_s16; codec->decode = decode_s16;#else codec->encode = encode_s16_swap; codec->decode = decode_s16_swap;#endif break; case 24: codec->block_align = 3 * atrack->channels; atrack->sample_format = LQT_SAMPLE_INT32; codec->encode = encode_s24_be; codec->decode = decode_s24_be; break; } }void quicktime_init_codec_sowt(quicktime_audio_map_t *atrack) { quicktime_pcm_codec_t *codec; quicktime_codec_t *codec_base = (quicktime_codec_t*)atrack->codec; /* Init public items */ codec_base->delete_acodec = delete_pcm; codec_base->decode_audio = decode_pcm; codec_base->encode_audio = encode_pcm; // codec_base->wav_id = 0x01; /* Init private items */ codec = calloc(1, sizeof(*codec)); codec_base->priv = codec; switch(atrack->track->mdia.minf.stbl.stsd.table[0].sample_size) { case 8: codec->block_align = atrack->channels; atrack->sample_format = LQT_SAMPLE_UINT8; codec->encode = encode_8; codec->decode = decode_8; break; case 16: codec->block_align = 2 * atrack->channels; atrack->sample_format = LQT_SAMPLE_INT16;#ifdef WORDS_BIGENDIAN codec->encode = encode_s16_swap; codec->decode = decode_s16_swap;#else codec->encode = encode_s16; codec->decode = decode_s16;#endif break; case 24: codec->block_align = 3 * atrack->channels; atrack->sample_format = LQT_SAMPLE_INT32; codec->encode = encode_s24_le; codec->decode = decode_s24_le; break; } }static void init_encode_in24(quicktime_t * file, int track) { quicktime_audio_map_t *atrack = &(file->atracks[track]); quicktime_pcm_codec_t *codec = ((quicktime_codec_t*)atrack->codec)->priv; quicktime_stsd_table_t *table = &(atrack->track->mdia.minf.stbl.stsd.table[0]); /* Initialize version 1 stsd */ quicktime_set_stsd_audio_v1(table, 1, 3, 3 * atrack->channels, 2);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -