// 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, &section);
				} 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, &section);
				}

				// 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);
				}
			}
Example #2
0
// 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);
}
Example #3
0
// 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, &section);

				// 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);
}