📄 pcmdecode.c
字号:
length = (unsigned int)(*temp_str++) << 24; length |= (unsigned int)(*temp_str++) << 16; length |= (unsigned int)(*temp_str++) << 8; length |= (unsigned int)(*temp_str++); check_length = 0; number_of_markers = (unsigned short)(*temp_str++) << 8; number_of_markers |= (unsigned short)(*temp_str++); check_length += 2; marker_counter = number_of_markers; while (marker_counter--) { short marker_id, string_length; marker_id = (unsigned short)(*temp_str++) << 8; marker_id |= (unsigned short)(*temp_str++); check_length += 2; marker_positions[marker_id] = (unsigned int)(*temp_str++) << 24; marker_positions[marker_id] |= (unsigned int)(*temp_str++) << 16; marker_positions[marker_id] |= (unsigned int)(*temp_str++) << 8; marker_positions[marker_id] |= (unsigned int)(*temp_str++); check_length += 4; string_length = (unsigned short)(*temp_str++); check_length++; // printf("string_length %x\n", string_length); for (ii = 0; ii <= (unsigned int)string_length; ii++) /* stupid Pascal string, get one more than the advertized length */ { ntemp_str[ii] = (*temp_str++); check_length++; } { //DPRINTF((M_TEXT("MARK string read: now at file position %lx\n"), ftell(input_samples_fp))); DPRINTF((M_TEXT("%s marker_positions[%d] = %lx\n"), ntemp_str, marker_id, marker_positions[marker_id])); } // printf("%s marker_positions[%d] = %lx\n", ntemp_str, marker_id, marker_positions[marker_id]); } if (check_length != length) { ERRORPRINTF((M_TEXT("AIFF MARK chunk parse error: %x != %x"), check_length, length)); return NULL; } if (number_of_markers > 1) { *loop_length = marker_positions[2] - marker_positions[1]; wave_sequence_length = marker_positions[2]; } //DPRINTF((M_TEXT("MARK end now at file position %lx\n"), ftell(input_samples_fp)); } else if (strncmp(temp_str, "NAME", 4) == 0) { unsigned int length; temp_str += 4; length = (unsigned int)(*temp_str++) << 24; length |= (unsigned int)(*temp_str++) << 16; length |= (unsigned int)(*temp_str++) << 8; length |= (unsigned int)(*temp_str++); for (ii = 0; ii < length; ii++) ntemp_str[ii] = (*temp_str++); ntemp_str[length] = 0; DPRINTF((M_TEXT("NAME '%s'\n"), ntemp_str)); } else if (strncmp(temp_str, "INST", 4) == 0) { temp_str += 4; DPRINTF((M_TEXT("Gobbling INST\n"))); temp_str += mac_gobble(temp_str); } else if (strncmp(temp_str, "SSND", 4) == 0) { temp_str += 4; number_of_bytes_of_sound_data = (unsigned int)(*temp_str++) << 24; number_of_bytes_of_sound_data |= (unsigned int)(*temp_str++) << 16; number_of_bytes_of_sound_data |= (unsigned int)(*temp_str++) << 8; number_of_bytes_of_sound_data |= (unsigned int)(*temp_str++); wave_offset = (unsigned int)(*temp_str++) << 24; wave_offset |= (unsigned int)(*temp_str++) << 16; wave_offset |= (unsigned int)(*temp_str++) << 8; wave_offset |= (unsigned int)(*temp_str++); block_alignment = (unsigned int)(*temp_str++) << 24; block_alignment |= (unsigned int)(*temp_str++) << 16; block_alignment |= (unsigned int)(*temp_str++) << 8; block_alignment |= (unsigned int)(*temp_str++); if (block_alignment != 0) { ERRORPRINTF((M_TEXT("AIFF header specifies nonzero blocksize?!?!"))); return NULL; } INFO_PRINTF((M_TEXT("AIFF format: \n Length = %ld\n"), number_of_bytes_of_sound_data)); INFO_PRINTF((M_TEXT(" number_of_channels = %d\n"), *number_of_channels)); INFO_PRINTF((M_TEXT(" samples_per_second = %d\n"), *samples_per_second)); INFO_PRINTF((M_TEXT(" bits_in_a_sample = %d\n"), bits_in_a_sample)); INFO_PRINTF((M_TEXT(" wave_offset = %d\n"), wave_offset)); break; } else { int jj; for (jj = 0; jj < 4; jj++) DPRINTF((M_TEXT("%02x "), temp_str[jj])); temp_str += 4; DPRINTF((M_TEXT("Gobbling %s\n"), temp_str)); //DPRINTF((M_TEXT("Gobble now at file position %lx\n"), ftell(input_samples_fp))); temp_str += mac_gobble(temp_str); } // DPRINTF((M_TEXT("AIFF end of loop: now at file position %lx\n"), ftell(input_samples_fp)); } } if (wave_sequence_length == 0) wave_sequence_length = number_of_bytes_of_sound_data; else wave_sequence_length *= (bits_in_a_sample/8); wavheader.iSamplesPerSec = *samples_per_second; wavheader.iBitsPerSample = bits_in_a_sample; wavheader.iChannels = *number_of_channels; wavheader.iBitrate = (*samples_per_second) * (*number_of_channels) * bits_in_a_sample; wavheader.iFramesize = block_alignment; wavheader.iDuration = /* ms */ 80 * wave_sequence_length / (*number_of_channels) / (*samples_per_second / 100) / bits_in_a_sample; wavheader.iLayer = WAVE_FORMAT_AIFF_PCM; //wavheader.iEmphasis } else DPRINTF((M_TEXT("NOT RIFF or AIFF file '%s'\n"), wav_header_to_scan)); if (*sample_size == 0) *sample_size = bits_in_a_sample/8; /* number of bytes in sample */ DPRINTF((M_TEXT("ssize %d\n"), *sample_size)); return temp_str;}static int process_header;void init_wav_decode(audiodecChangeInfo *ci){ process_header = 1; /* set defaults */ ci->sampling_rate = 44100; ci->channels = 2;}void set_no_header_wav_decode(void){ process_header = 0;}int decode_wav_audio(audiodecChangeInfo *ci, short *p_outbuf, int *out_size, unsigned char *in_buf, int inbuf_size){ static int loop_length; static int sample_size=0; /* used only with WAVE_FORMAT_PCM!! */ int num_bytes_to_process = inbuf_size < MAX_PROCESS_PER_CALL_WAVE_FORMAT_PCM ? inbuf_size : MAX_PROCESS_PER_CALL_WAVE_FORMAT_PCM; int ii, header_length = 0; if (process_header) { unsigned char *out_buf = scan_wave_header(in_buf, &sample_size, &loop_length, &ci->channels, &ci->sampling_rate); process_header = 0; header_length = (out_buf - in_buf); num_bytes_to_process -= header_length; DPRINTF((M_TEXT("header_length %d\n"), header_length)); in_buf = out_buf; *out_size = 0; if (wavheader.iLayer != WAVE_FORMAT_PCM) return header_length; } //else /* do NOT do this since ci->bits_per_sample is changed later! */ // sample_size = ci->bits_per_sample >> 3; if ((wavheader.iLayer == WAVE_FORMAT_AIFF_PCM) || (wavheader.iLayer == WAVE_FORMAT_PCM) || (wavheader.iLayer == WAVE_FORMAT_PCM_EXTENDED)) { int jj; unsigned short *obuf = (unsigned short *)p_outbuf; unsigned char *ibuf = (unsigned char *)in_buf; unsigned int tester; //MK051606 if(sample_size == 0) sample_size = wavheader.iBitsPerSample >> 3; switch (sample_size) // in bytes { case 3: tester = num_bytes_to_process / 3; num_bytes_to_process = tester * 3; // must be a multiple of 24 bits if (big_endian) { for (jj = 0, ii = 0; ii < num_bytes_to_process; ii+=3, jj+=2) { unsigned short out, out2; out2 = *ibuf++; out = *ibuf++; ibuf++; // discard low 8 bits, could round here *obuf++ = out | (out2 << 8); } } else { for (jj = 0, ii = 0; ii < num_bytes_to_process; ii+=3, jj+=2) { unsigned short out, out2; ibuf++; // discard low 8 bits, could round here out = *ibuf++; out2 = *ibuf++; *obuf++ = out | (out2 << 8); } } num_bytes_to_process = ii; *out_size = jj; break; case 2: if (big_endian) flip_byte_order16((unsigned short *)p_outbuf, (unsigned short *)in_buf, num_bytes_to_process); else memcpy(p_outbuf, in_buf, num_bytes_to_process); *out_size = num_bytes_to_process; break; case 1: for (ii = 0; ii < num_bytes_to_process; ii++) { unsigned short out; out = *ibuf++; out <<= 8; *obuf++ = out + (unsigned int)0x8000; } num_bytes_to_process = ii; *out_size = ii << 1; break; default: DPRINTF((M_TEXT("sample size %d not supported\n"), sample_size)); *out_size = 0; return -1; } do_pcm_conversions((char *)p_outbuf, out_size); return num_bytes_to_process + header_length; } else if ((wavheader.iLayer == WAVE_FORMAT_ADPCM) || (wavheader.iLayer == WAVE_FORMAT_DVI_ADPCM)) { if (wavheader.iFramesize <= (unsigned int)(inbuf_size - header_length)) { if (wavheader.iLayer == WAVE_FORMAT_DVI_ADPCM) *out_size = 2 * ms_ima_adpcm_decode_block(p_outbuf, in_buf, wavheader.iChannels, wavheader.iFramesize); else *out_size = 2 * ms_adpcm_decode_block(p_outbuf, in_buf, wavheader.iChannels, wavheader.iFramesize); do_pcm_conversions((char *)p_outbuf, out_size); return header_length + wavheader.iFramesize; } else /* should only happen on last frame */ { *out_size = 0; return inbuf_size; } } else if ((wavheader.iLayer == WAVE_FORMAT_MULAW) || (wavheader.iLayer == WAVE_FORMAT_ALAW)) { int len; int ll = inbuf_size; // demux_read_data(sh_audio->ds,buf,minlen/2); unsigned short *dd = (unsigned short *) p_outbuf; unsigned char *ss = in_buf; len = 2 * ll; if (wavheader.iLayer == WAVE_FORMAT_ALAW) // also 0x77616C61 { /* aLaw */ while (ll > 0) { --ll; dd[ll] = alaw2short[ss[ll]]; } } else { /* uLaw */ while (ll > 0) { --ll; dd[ll] = ulaw2short[ss[ll]]; } } *out_size = len; } else { ERRORPRINTF((M_TEXT("pcmdecode: unsupported format %x\n"), wavheader.iLayer)); *out_size = 0; return inbuf_size; } do_pcm_conversions((char *)p_outbuf, out_size); return inbuf_size;}/* * MPEG LPCM header : * - PES header 0 - private stream ID (8 bits) == 0xA0 (A1 == MLP) 1 - frame number (8 bits) 2/3 - unknown (16 bits) == 0x0003 ? 4 - unknown (4 bits) 4 - current frame (4 bits) 5 - unknown (2 bits) 5 - frequency (2 bits) 0 == 48 kHz, 1 == 32 kHz, 2 == ?, 3 == ? 5 - unknown (1 bit) 5 - number of channels - 1 (3 bits) 1 == 2 channels 6 - start code (8 bits) == 0x80 */ #if 0DVD LPCM HeaderThe audio frame size for LPCM packets in a VOB file is always 150 PTS ticks. For LPCM packets in an AOB file, the audio frame size for a stereo stream is as follows: Size in Bytes Size inSamples 16-bit 20-bit 24-bit 44.1KHz or 48KHz 160 200 240 40 88.2KHz or 96KHz 320 400 480 80 176.4KHz or 192KHz 640 800 960 160 The LPCM header is as follows:Offset Size (bytes) Description 0 1 Sub-stream ID. Unconfirmed, but possibly 0xa0 for LPCM and 0xa1 for MLP 1 1 Continuity Counter - counts from 0x00 to 0x1f and then wraps to 0x00. 2 2 LPCM_header_length The following applies to LPCM packets (not MLP) 4 2 Byte pointer to start of first audio frame. 6 1 Unknown - e.g. 0x10 for stereo, 0x00 for surround 7 1 Sample size (high nibble - Channel Group 1, low nibble - Channel Group 2).0x0=16-bit, 0x1=20-bit, 0x2=24-bit, 0xf=Channel Group not used. 8 1 Samplerate (high nibble - Channel Group 1, low nibble - Channel Group 2).0x0=48KHz, 0x1=96KHz, 0x2=192KHz,0x8=44.1KHz, 0x9=88.2KHz, 0xa=176.4KHz, 0xf=Channel Group not used.e.g. 0x0f=48KHz Stereo, 0x88=44.1KHz Surround 9 1 Unknown - e.g. 0x00 10 1 Channel Group Assignment (see below). 11 1 Unknown - e.g. 0x80 12 var Padding - zero Channel Group AssignmentsThe DVD-Audio specification supports splitting a multi-channel track into two groups of channels, where the channels assigned to group 2 have a lower samplerate/bit-depth than the channels in group 1. The valid assignments are as follows:ID Chan. 0 Chan. 1 Chan. 2 Chan. 3 Chan. 4 Chan. 5 0 C 1 L R 2 L R S 3 L R Ls Rs 4 L R Lfe 5 L R Lfe S 6 L R Lfe Ls Rs 7 L R C 8 L R C S 9 L R C Ls Rs 10 L R C Lfe 11 L R C Lfe S 12 L R C Lfe Ls Rs 13 L R C S 14 L R C Ls Rs 15 L R C Lfe 16 L R C Lfe S 17 L R C Lfe Ls Rs 18 L R Ls Rs Lfe 19 L R Ls Rs C 20 L R Ls Rs C Lfe Group 1 Group 2 where L=Front Left, R=Front Right, C=Centre, Ls=Left Surround, Rs=Right Surround, S=Surround and Lfe=Low frequency effects#endif int decode_pcm_audio(audiodecChangeInfo *ci, short *p_outbuf, int *out_size, unsigned char *in_buf, int inbuf_size, int sample_size, int big_endian){ int ii; int jj; unsigned short *obuf = (unsigned short *)p_outbuf; unsigned char *ibuf = (unsigned char *)in_buf; unsigned int tester; int num_bytes_to_process = inbuf_size < MAX_PROCESS_PER_CALL_WAVE_FORMAT_PCM ? inbuf_size : MAX_PROCESS_PER_CALL_WAVE_FORMAT_PCM; DPRINTF((M_TEXT("PCMDEC raw %d\n"), inbuf_size)); switch (sample_size) // in bytes { case 3: tester = num_bytes_to_process / 3; num_bytes_to_process = tester * 3; // must be a multipl
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -