// Read // // Returns number of bytes actually read. // // Returns -1 if there is nothing more to be read. This function can return 0, since // sometimes the amount of bytes requested is too small for the ACM decompression to // locate a suitable block int WaveFile::Read(ubyte *pbDest, uint cbSize, int service) { void *dest_buf=NULL, *uncompressed_wave_data; int rc, uncompressed_bytes_written, section, last_section = -1, byte_order = 0; uint src_bytes_used, convert_len, num_bytes_desired=0, num_bytes_read; // nprintf(("Alan","Reqeusted: %d\n", cbSize)); #if BYTE_ORDER == BIG_ENDIAN byte_order = 1; #endif if ( service ) { uncompressed_wave_data = Wavedata_service_buffer; } else { uncompressed_wave_data = Wavedata_load_buffer; } switch ( m_wave_format ) { case WAVE_FORMAT_PCM: num_bytes_desired = cbSize; dest_buf = pbDest; break; case WAVE_FORMAT_ADPCM: { if ( !m_hStream_open ) { if ( !ACM_stream_open(m_pwfmt_original, &m_wfxDest, (void**)&m_hStream, m_bits_per_sample_uncompressed) ) { m_hStream_open = 1; } else { Int3(); } } num_bytes_desired = cbSize; if ( service ) { dest_buf = Compressed_service_buffer; } else { dest_buf = Compressed_buffer; } if ( num_bytes_desired <= 0 ) { num_bytes_desired = 0; // nprintf(("Alan","No bytes required for ADPCM time interval\n")); } else { num_bytes_desired = ACM_query_source_size((void*)m_hStream, cbSize); // nprintf(("Alan","Num bytes desired: %d\n", num_bytes_desired)); } break; } case OGG_FORMAT_VORBIS: num_bytes_desired = cbSize; dest_buf = pbDest; break; case WAVE_FORMAT_IEEE_FLOAT: { num_bytes_desired = cbSize; if (m_wfmt.wBitsPerSample == 32) { dest_buf = pbDest; } else { if (service) { dest_buf = Compressed_service_buffer; } else { dest_buf = Compressed_buffer; } } break; } default: nprintf(("SOUND", "SOUND => Not supporting %d format for playing wave files\n", m_wave_format)); Int3(); break; } // end switch num_bytes_read = 0; convert_len = 0; src_bytes_used = 0; // read data from disk if ( m_data_bytes_left <= 0 ) { num_bytes_read = 0; uncompressed_bytes_written = 0; return -1; } if ( (m_data_bytes_left > 0) && (num_bytes_desired > 0) ) { int actual_read = 0; if ( num_bytes_desired <= (uint)m_data_bytes_left ) { num_bytes_read = num_bytes_desired; } else { num_bytes_read = m_data_bytes_left; } // OGG reading is special if ( m_wave_format == OGG_FORMAT_VORBIS ) { int sign = (m_wfmt.wBitsPerSample == 8) ? 0 : 1; int sample_size = sizeof(float) * m_wfmt.nChannels; while ( !m_abort_next_read && ((uint)actual_read < num_bytes_read)) { float **pcm = NULL; if (m_wfmt.wBitsPerSample == 32) { rc = ov_read_float(&m_snd_info.vorbis_file, &pcm, (num_bytes_read - actual_read) / sample_size, §ion); } else { rc = ov_read(&m_snd_info.vorbis_file, (char *)dest_buf + actual_read, num_bytes_read - actual_read, byte_order, m_wfmt.wBitsPerSample / 8, sign, §ion); } // fail if the bitstream changes, shouldn't get this far if that's the case though if ((last_section != -1) && (last_section != section)) { mprintf(("AUDIOSTR => OGG reading error: We don't handle bitstream changes!\n")); goto READ_ERROR; } if ( rc > 0 ) { if (m_wfmt.wBitsPerSample == 32) { float *out_p = (float*)((ubyte*)dest_buf + actual_read); for (int i = 0; i < rc; i++) { for (int j = 0; j < m_wfmt.nChannels; j++) { *out_p++ = pcm[j][i]; } } actual_read += (rc * m_wfmt.nBlockAlign); } else { actual_read += rc; } last_section = section; } else if ( rc == 0 ) { break; } else if ( rc < 0 ) { if ( dbg_print_ogg_error(m_wFilename, rc) ) { // must be a fatal error goto READ_ERROR; } else { // not fatal, just continue on break; } } } } // IEEE FLOAT is special too, downsampling can give short buffers else if (m_wave_format == WAVE_FORMAT_IEEE_FLOAT) { while ( !m_abort_next_read && ((uint)actual_read < num_bytes_read) ) { rc = mmioRead(m_snd_info.cfp, (char *)dest_buf, num_bytes_read); if (rc <= 0) { break; } #if BYTE_ORDER == BIG_ENDIAN // need to byte-swap before any later conversions float *swap_tmp; for (int i = 0; i < rc; i += sizeof(float)) { swap_tmp = (float *)((ubyte*)dest_buf + i); *swap_tmp = INTEL_FLOAT(swap_tmp); } #endif if (m_wfmt.wBitsPerSample == 32) { actual_read = rc; } else if (m_wfmt.wBitsPerSample == 16) { float *in_p = (float*)dest_buf; short *out_p = (short*)((ubyte*)uncompressed_wave_data + actual_read); int end = rc / sizeof(float); for (int i = 0; i < end; i++) { int i_val = (int)(in_p[i] * 32767.0f + 0.5f); CLAMP(i_val, -32768, 32767); *out_p++ = (short)i_val; } actual_read += (rc >> 1); } else { Assert( m_wfmt.wBitsPerSample == 8 ); float *in_p = (float*)dest_buf; ubyte *out_p = (ubyte*)((ubyte*)uncompressed_wave_data + actual_read); int end = num_bytes_read / sizeof(float); for (int i = 0; i < end; i++) { int i_val = (int)(in_p[i] * 127.0f + 0.5f) + 128; CLAMP(i_val, 0, 255); *out_p++ = (ubyte)i_val; } actual_read += (rc >> 2); } }
// Read // // Returns number of bytes actually read. // // Returns -1 if there is nothing more to be read. This function can return 0, since // sometimes the amount of bytes requested is too small for the ACM decompression to // locate a suitable block int WaveFile::Read(BYTE *pbDest, UINT cbSize, int service) { unsigned char *dest_buf=NULL, *uncompressed_wave_data; int rc, uncompressed_bytes_written; unsigned int src_bytes_used, convert_len, num_bytes_desired=0, num_bytes_read; // nprintf(("Alan","Reqeusted: %d\n", cbSize)); if ( service ) { uncompressed_wave_data = Wavedata_service_buffer; } else { uncompressed_wave_data = Wavedata_load_buffer; } switch ( m_wave_format ) { case WAVE_FORMAT_PCM: num_bytes_desired = cbSize; dest_buf = pbDest; break; case WAVE_FORMAT_ADPCM: if ( !m_hStream_open ) { if ( !ACM_stream_open(m_pwfmt_original, &m_wfxDest, (void**)&m_hStream), m_bits_per_sample_uncompressed ) { m_hStream_open = 1; } else { Int3(); } } num_bytes_desired = cbSize; if ( service ) { dest_buf = Compressed_service_buffer; } else { dest_buf = Compressed_buffer; } if ( num_bytes_desired <= 0 ) { num_bytes_desired = 0; // nprintf(("Alan","No bytes required for ADPCM time interval\n")); } else { num_bytes_desired = ACM_query_source_size((void*)m_hStream, cbSize); // nprintf(("Alan","Num bytes desired: %d\n", num_bytes_desired)); } break; default: nprintf(("SOUND", "SOUND => Not supporting %d format for playing wave files\n")); Int3(); break; } // end switch num_bytes_read = 0; convert_len = 0; src_bytes_used = 0; // read data from disk if ( m_data_bytes_left <= 0 ) { num_bytes_read = 0; uncompressed_bytes_written = 0; return -1; } if ( m_data_bytes_left > 0 && num_bytes_desired > 0 ) { int actual_read; if ( num_bytes_desired <= (unsigned int)m_data_bytes_left ) { num_bytes_read = num_bytes_desired; } else { num_bytes_read = m_data_bytes_left; } actual_read = mmioRead( cfp, (char *)dest_buf, num_bytes_read ); if ( (actual_read <= 0) || (m_abort_next_read) ) { num_bytes_read = 0; uncompressed_bytes_written = 0; return -1; } if ( num_bytes_desired >= (unsigned int)m_data_bytes_left ) { m_abort_next_read = 1; } num_bytes_read = actual_read; } // convert data if necessary, to PCM if ( m_wave_format == WAVE_FORMAT_ADPCM ) { if ( num_bytes_read > 0 ) { rc = ACM_convert((void*)m_hStream, dest_buf, num_bytes_read, uncompressed_wave_data, BIGBUF_SIZE, &convert_len, &src_bytes_used); if ( rc == -1 ) { goto READ_ERROR; } if ( convert_len == 0 ) { Int3(); } } Assert(src_bytes_used <= num_bytes_read); if ( src_bytes_used < num_bytes_read ) { // seek back file pointer to reposition before unused source data mmioSeek(cfp, src_bytes_used - num_bytes_read, SEEK_CUR); } // Adjust number of bytes left m_data_bytes_left -= src_bytes_used; m_nBytesPlayed += src_bytes_used; uncompressed_bytes_written = convert_len; // Successful read, keep running total of number of data bytes read goto READ_DONE; } else { // Successful read, keep running total of number of data bytes read // Adjust number of bytes left m_data_bytes_left -= num_bytes_read; m_nBytesPlayed += num_bytes_read; uncompressed_bytes_written = num_bytes_read; goto READ_DONE; } READ_ERROR: num_bytes_read = 0; uncompressed_bytes_written = 0; READ_DONE: m_total_uncompressed_bytes_read += uncompressed_bytes_written; // nprintf(("Alan","Read: %d\n", uncompressed_bytes_written)); return (uncompressed_bytes_written); }
// Read // // Returns number of bytes actually read. // // Returns -1 if there is nothing more to be read. This function can return 0, since // sometimes the amount of bytes requested is too small for the ACM decompression to // locate a suitable block int WaveFile::Read(BYTE* pbDest, UINT cbSize, int service) { unsigned char* dest_buf = NULL, *uncompressed_wave_data; int rc, uncompressed_bytes_written, section, last_section = -1, byte_order = 0; unsigned int src_bytes_used, convert_len, num_bytes_desired = 0, num_bytes_read; // nprintf(("Alan","Reqeusted: %d\n", cbSize)); #if BYTE_ORDER == BIG_ENDIAN byte_order = 1; #endif if (service) { uncompressed_wave_data = Wavedata_service_buffer; } else { uncompressed_wave_data = Wavedata_load_buffer; } switch (m_wave_format) { case WAVE_FORMAT_PCM: num_bytes_desired = cbSize; dest_buf = pbDest; break; case WAVE_FORMAT_ADPCM: if (!m_hStream_open) { if (!ACM_stream_open(m_pwfmt_original, &m_wfxDest, (void**)&m_hStream), m_wfmt.wBitsPerSample) { m_hStream_open = 1; } else { Int3(); } } num_bytes_desired = cbSize; if (service) { dest_buf = Compressed_service_buffer; } else { dest_buf = Compressed_buffer; } if (num_bytes_desired <= 0) { num_bytes_desired = 0; // nprintf(("Alan","No bytes required for ADPCM time interval\n")); } else { num_bytes_desired = ACM_query_source_size((void*)m_hStream, cbSize); // nprintf(("Alan","Num bytes desired: %d\n", num_bytes_desired)); } break; case OGG_FORMAT_VORBIS: num_bytes_desired = cbSize; dest_buf = pbDest; break; default: nprintf(("SOUND", "SOUND => Not supporting %d format for playing wave files\n")); Int3(); break; } // end switch num_bytes_read = 0; convert_len = 0; src_bytes_used = 0; // read data from disk if (m_data_bytes_left <= 0) { num_bytes_read = 0; uncompressed_bytes_written = 0; return -1; } if ((m_data_bytes_left > 0) && (num_bytes_desired > 0)) { int actual_read = 0; if (num_bytes_desired <= (uint)m_data_bytes_left) { num_bytes_read = num_bytes_desired; } else { num_bytes_read = m_data_bytes_left; } // OGG reading is special if (m_wave_format == OGG_FORMAT_VORBIS) { while (!m_abort_next_read && ((uint)actual_read < num_bytes_read)) { rc = ov_read(&m_snd_info.vorbis_file, (char*)dest_buf + actual_read, num_bytes_read - actual_read, byte_order, m_wfmt.wBitsPerSample / 8, 1, §ion); // fail if the bitstream changes, shouldn't get this far if that's the case though if ((last_section != -1) && (last_section != section)) { mprintf(("AUDIOSTR => OGG reading error: We don't handle bitstream changes!\n")); goto READ_ERROR; } if (rc > 0) { last_section = section; actual_read += rc; } else if (rc == 0) { break; } else if (rc == OV_EBADLINK) { goto READ_ERROR; } } } // standard WAVE reading else { actual_read = mmioRead(m_snd_info.cfp, (char*)dest_buf, num_bytes_read); } if ((actual_read <= 0) || (m_abort_next_read)) { num_bytes_read = 0; uncompressed_bytes_written = 0; return -1; } if (num_bytes_desired >= (uint)m_data_bytes_left) { m_abort_next_read = 1; } num_bytes_read = actual_read; } // convert data if necessary, to PCM if (m_wave_format == WAVE_FORMAT_ADPCM) { if (num_bytes_read > 0) { rc = ACM_convert((void*)m_hStream, dest_buf, num_bytes_read, uncompressed_wave_data, BIGBUF_SIZE, &convert_len, &src_bytes_used); if (rc == -1) { goto READ_ERROR; } if (convert_len == 0) { Int3(); } } Assert(src_bytes_used <= num_bytes_read); if (src_bytes_used < num_bytes_read) { // seek back file pointer to reposition before unused source data mmioSeek(m_snd_info.cfp, src_bytes_used - num_bytes_read, SEEK_CUR); } // Adjust number of bytes left m_data_bytes_left -= src_bytes_used; m_nBytesPlayed += src_bytes_used; uncompressed_bytes_written = convert_len; // Successful read, keep running total of number of data bytes read goto READ_DONE; } else { // Successful read, keep running total of number of data bytes read // Adjust number of bytes left m_data_bytes_left -= num_bytes_read; m_nBytesPlayed += num_bytes_read; uncompressed_bytes_written = num_bytes_read; goto READ_DONE; } READ_ERROR: num_bytes_read = 0; uncompressed_bytes_written = 0; READ_DONE: m_total_uncompressed_bytes_read += uncompressed_bytes_written; // nprintf(("Alan","Read: %d\n", uncompressed_bytes_written)); return (uncompressed_bytes_written); }