/*********************************************************************** * mmioAdvance [MMSYSTEM.1219] */ MMRESULT16 WINAPI mmioAdvance16(HMMIO16 hmmio, MMIOINFO16* lpmmioinfo, UINT16 uFlags) { MMIOINFO mmioinfo; LRESULT ret; /* WARNING: this heavily relies on mmioAdvance implementation (for choosing which * fields to init */ if (lpmmioinfo) { mmioinfo.pchBuffer = MapSL((DWORD)lpmmioinfo->pchBuffer); mmioinfo.pchNext = MapSL((DWORD)lpmmioinfo->pchNext); mmioinfo.dwFlags = lpmmioinfo->dwFlags; mmioinfo.lBufOffset = lpmmioinfo->lBufOffset; ret = mmioAdvance(HMMIO_32(hmmio), &mmioinfo, uFlags); } else ret = mmioAdvance(HMMIO_32(hmmio), NULL, uFlags); if (ret != MMSYSERR_NOERROR) return ret; if (lpmmioinfo) { lpmmioinfo->dwFlags = mmioinfo.dwFlags; lpmmioinfo->pchNext = (void*)(lpmmioinfo->pchBuffer + (mmioinfo.pchNext - mmioinfo.pchBuffer)); lpmmioinfo->pchEndRead = (void*)(lpmmioinfo->pchBuffer + (mmioinfo.pchEndRead - mmioinfo.pchBuffer)); lpmmioinfo->pchEndWrite = (void*)(lpmmioinfo->pchBuffer + (mmioinfo.pchEndWrite - mmioinfo.pchBuffer)); lpmmioinfo->lBufOffset = mmioinfo.lBufOffset; lpmmioinfo->lDiskOffset = mmioinfo.lDiskOffset; } return MMSYSERR_NOERROR; }
//----------------------------------------------------------------------------- // Name: CWaveFile::Write() // Desc: Writes data to the open wave file //----------------------------------------------------------------------------- HRESULT CWaveFile::Write( UINT nSizeToWrite, BYTE* pbSrcData, UINT* pnSizeWrote ) { UINT cT; if( m_bIsReadingFromMemory ) return E_NOTIMPL; if( m_hmmio == NULL ) return CO_E_NOTINITIALIZED; if( pnSizeWrote == NULL || pbSrcData == NULL ) return E_INVALIDARG; *pnSizeWrote = 0; for( cT = 0; cT < nSizeToWrite; cT++ ) { if( m_mmioinfoOut.pchNext == m_mmioinfoOut.pchEndWrite ) { m_mmioinfoOut.dwFlags |= MMIO_DIRTY; if( 0 != mmioAdvance( m_hmmio, &m_mmioinfoOut, MMIO_WRITE ) ) return DXTRACE_ERR( TEXT("mmioAdvance"), E_FAIL ); } *((BYTE*)m_mmioinfoOut.pchNext) = *((BYTE*)pbSrcData+cT); (BYTE*)m_mmioinfoOut.pchNext++; (*pnSizeWrote)++; } return S_OK; }
//----------------------------------------------------------------------------- // Name: WaveWriteFile() // Desc: This routine will write out data to a wave file. Make sure we're // created the chuck before calling this function. //----------------------------------------------------------------------------- HRESULT WaveWriteFile( HMMIO hmmioOut, UINT cbWrite, BYTE* pbSrc, MMCKINFO* pckOut, UINT* cbActualWrite, MMIOINFO* pmmioinfoOut ) { UINT cT; *cbActualWrite = 0; for( cT = 0; cT < cbWrite; cT++ ) { if( pmmioinfoOut->pchNext == pmmioinfoOut->pchEndWrite ) { pmmioinfoOut->dwFlags |= MMIO_DIRTY; if( 0 != mmioAdvance( hmmioOut, pmmioinfoOut, MMIO_WRITE ) ) return E_FAIL; } *((BYTE*)pmmioinfoOut->pchNext) = *((BYTE*)pbSrc+cT); (BYTE*)pmmioinfoOut->pchNext++; (*cbActualWrite)++; } return S_OK; }
int WaveWriteFile( HMMIO hmmioOut, // (IN) UINT cbWrite, // (IN) BYTE *pbSrc, // (IN) MMCKINFO *pckOut, // (IN) UINT *cbActualWrite, // (OUT) MMIOINFO *pmmioinfoOut // (IN) ) { int nError=0; UINT cT; *cbActualWrite = 0; for (cT=0; cT < cbWrite; cT++) { if (pmmioinfoOut->pchNext == pmmioinfoOut->pchEndWrite) { pmmioinfoOut->dwFlags |= MMIO_DIRTY; if ((nError = mmioAdvance(hmmioOut, pmmioinfoOut, MMIO_WRITE)) != 0) { goto ERROR_CANNOT_WRITE; } } *((BYTE*)pmmioinfoOut->pchNext)++ = *((BYTE*)pbSrc+cT); (*cbActualWrite)++; } ERROR_CANNOT_WRITE: // What to do here? Well, for now, nothing, just return that error. // (maybe delete the file later?) return(nError); }
int WaveReadFile( HMMIO hmmioIn, // IN UINT cbRead, // IN BYTE *pbDest, // IN MMCKINFO *pckIn, // IN. UINT *cbActualRead // OUT. ) { MMIOINFO mmioinfoIn; // current status of <hmmioIn> int nError=0; UINT cT, cbDataIn; if ((nError = mmioGetInfo(hmmioIn, &mmioinfoIn, 0)) != 0) { goto ERROR_CANNOT_READ; } cbDataIn = cbRead; if (cbDataIn > pckIn->cksize) cbDataIn = pckIn->cksize; pckIn->cksize -= cbDataIn; for (cT = 0; cT < cbDataIn; cT++) { /* Copy the bytes from the io to the buffer. */ if (mmioinfoIn.pchNext == mmioinfoIn.pchEndRead) { if ((nError = mmioAdvance(hmmioIn, &mmioinfoIn, MMIO_READ)) != 0) { goto ERROR_CANNOT_READ; } if (mmioinfoIn.pchNext == mmioinfoIn.pchEndRead) { nError = ER_CORRUPTWAVEFILE; goto ERROR_CANNOT_READ; } } // Actual copy. *((BYTE*)pbDest+cT) = *((BYTE*)mmioinfoIn.pchNext)++; } if ((nError = mmioSetInfo(hmmioIn, &mmioinfoIn, 0)) != 0) { goto ERROR_CANNOT_READ; } *cbActualRead = cbDataIn; goto FINISHED_READING; ERROR_CANNOT_READ: *cbActualRead = 0; FINISHED_READING: return(nError); }
UINT WaveFile::Read (BYTE * pbDest, UINT cbSize) { MMIOINFO mmioinfo; UINT cb; DOUT ("WaveFile::Read\n\r"); // Use direct buffer access for reads to maximize performance if (m_mmr = mmioGetInfo (m_hmmio, &mmioinfo, 0)) { goto READ_ERROR; } // Limit read size to chunk size cbSize = (cbSize > m_mmckiData.cksize) ? m_mmckiData.cksize : cbSize; // Adjust chunk size m_mmckiData.cksize -= cbSize; // Copy bytes from MMIO buffer for (cb = 0; cb < cbSize; cb++) { // Advance buffer if necessary if (mmioinfo.pchNext == mmioinfo.pchEndRead) { if (m_mmr = mmioAdvance (m_hmmio, &mmioinfo, MMIO_READ)) { goto READ_ERROR; } if (mmioinfo.pchNext == mmioinfo.pchEndRead) { m_mmr = MMIOERR_CANNOTREAD; goto READ_ERROR; } } // Actual copy // *((BYTE*)pbDest+cb) = *((BYTE*)mmioinfo.pchNext)++; if( g_bBGMPlaying ) *(pbDest+cb) = *(mmioinfo.pchNext)++; } // End direct buffer access if (m_mmr = mmioSetInfo (m_hmmio, &mmioinfo, 0)) { goto READ_ERROR; } // Successful read, keep running total of number of data bytes read m_nBytesPlayed += cbSize; goto READ_DONE; READ_ERROR: cbSize = 0; READ_DONE: return (cbSize); }
void write( const std::vector<std::int16_t*> buffers, std::size_t frames ) { for ( std::size_t frame = 0; frame < frames; frame++ ) { for ( std::size_t channel = 0; channel < buffers.size(); channel++ ) { if ( data_info.pchEndWrite - data_info.pchNext < static_cast<long>( sizeof( std::int16_t ) ) ) { data_info.dwFlags |= MMIO_DIRTY; CHECKED(mmioAdvance( mmio, &data_info, MMIO_WRITE )); } std::memcpy( data_info.pchNext, &( buffers[channel][frame] ), sizeof( std::int16_t ) ); data_info.pchNext += sizeof( std::int16_t ); } } }
HRESULT WaveDecoder::Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead ) { MMIOINFO mmioinfoIn; // current status of m_hmmio if( m_hmmio == NULL ) return CO_E_NOTINITIALIZED; if( pBuffer == NULL || pdwSizeRead == NULL ) return E_INVALIDARG; if( pdwSizeRead != NULL ) *pdwSizeRead = 0; if( 0 != mmioGetInfo( m_hmmio, &mmioinfoIn, 0 ) ) return E_FAIL; UINT cbDataIn = dwSizeToRead; if( cbDataIn > m_ck.cksize ) cbDataIn = m_ck.cksize; m_ck.cksize -= cbDataIn; for( DWORD cT = 0; cT < cbDataIn; cT++ ) { // Copy the bytes from the io to the buffer. if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) { if( 0 != mmioAdvance( m_hmmio, &mmioinfoIn, MMIO_READ ) ) return E_FAIL; if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) return E_FAIL; } // Actual copy. *( ( BYTE* )pBuffer + cT ) = *( ( BYTE* )mmioinfoIn.pchNext ); mmioinfoIn.pchNext++; } if( 0 != mmioSetInfo( m_hmmio, &mmioinfoIn, 0 ) ) return E_FAIL; if( pdwSizeRead != NULL ) *pdwSizeRead = cbDataIn; return S_OK; }
void CWaveFile::WriteWave(char *Data, int Size) { // Save data to the file // int cT; for (cT = 0; cT < Size; cT++) { if (mmioinfoOut.pchNext == mmioinfoOut.pchEndWrite) { mmioinfoOut.dwFlags |= MMIO_DIRTY; mmioAdvance(hmmioOut, &mmioinfoOut, MMIO_WRITE); } *((BYTE*)mmioinfoOut.pchNext) = *((BYTE*)Data + cT); mmioinfoOut.pchNext++; } }
/** 書き込み * * @author SAM (T&GG, Org.)<*****@*****.**> * @date 2004/01/21 4:48:29 * Copyright (C) 2001,2002,2003,2004 SAM (T&GG, Org.). All rights reserved. */ HRslt WavFile::write(const void *src, size_t size, size_t * const wrotesize) { if( !(flags_&WRITE) ) return E_FAIL; if( !hmmio_ ) return CO_E_NOTINITIALIZED; if( !src ) return E_INVALIDARG; if(wrotesize) *wrotesize = 0; for(size_t cT = 0; cT < size; cT++ ) { if( write_mmioinfo_.pchNext == write_mmioinfo_.pchEndWrite ) { write_mmioinfo_.dwFlags |= MMIO_DIRTY; if( 0 != mmioAdvance( hmmio_, &write_mmioinfo_, MMIO_WRITE ) ) return DXTRACE_ERR( TEXT("mmioAdvance"), E_FAIL ); } *write_mmioinfo_.pchNext = *((BYTE*)src+cT); write_mmioinfo_.pchNext++; if(wrotesize) (*wrotesize)++; } return S_OK; }
//----------------------------------------------------------------------------- // Name: WaveReadFile() // Desc: Reads wave data from the wave file. Make sure we're descended into // the data chunk before calling this function. // hmmioIn - Handle to mmio. // cbRead - # of bytes to read. // pbDest - Destination buffer to put bytes. // cbActualRead - # of bytes actually read. //----------------------------------------------------------------------------- HRESULT WaveReadFile( HMMIO hmmioIn, UINT cbRead, BYTE* pbDest, MMCKINFO* pckIn, UINT* cbActualRead ) { MMIOINFO mmioinfoIn; // current status of <hmmioIn> *cbActualRead = 0; if( 0 != mmioGetInfo( hmmioIn, &mmioinfoIn, 0 ) ) return E_FAIL; UINT cbDataIn = cbRead; if( cbDataIn > pckIn->cksize ) cbDataIn = pckIn->cksize; pckIn->cksize -= cbDataIn; for( DWORD cT = 0; cT < cbDataIn; cT++ ) { // Copy the bytes from the io to the buffer. if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) { if( 0 != mmioAdvance( hmmioIn, &mmioinfoIn, MMIO_READ ) ) return E_FAIL; if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) return E_FAIL; } // Actual copy. *((BYTE*)pbDest+cT) = *((BYTE*)mmioinfoIn.pchNext); mmioinfoIn.pchNext++; } if( 0 != mmioSetInfo( hmmioIn, &mmioinfoIn, 0 ) ) return E_FAIL; *cbActualRead = cbDataIn; return S_OK; }
BOOL TinyWaveFile::Read(BYTE* lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead) { if (hmmio == NULL) return FALSE; *lpNumberOfBytesRead = 0; MMIOINFO mmioinfo; if (MMSYSERR_NOERROR != mmioGetInfo(hmmio, &mmioinfo, 0)) return FALSE; UINT cbDataIn = nNumberOfBytesToRead; if (cbDataIn > dwSize) cbDataIn = dwLSize; dwLSize -= cbDataIn; for (DWORD cT = 0; cT < cbDataIn; cT++) { if (mmioinfo.pchNext == mmioinfo.pchEndRead) { if (MMSYSERR_NOERROR != mmioAdvance(hmmio, &mmioinfo, MMIO_READ)) return FALSE; if (mmioinfo.pchNext == mmioinfo.pchEndRead) return FALSE; } *((BYTE*)lpBuffer + cT) = *((BYTE*)mmioinfo.pchNext); mmioinfo.pchNext++; } if (MMSYSERR_NOERROR != mmioSetInfo(hmmio, &mmioinfo, 0)) return FALSE; *lpNumberOfBytesRead = cbDataIn; return TRUE; }
static void test_mmio_end_of_file(void) { char test_file[MAX_PATH], buffer[128], data[16]; MMIOINFO mmio; HMMIO hmmio; LONG ret; MMRESULT res; if (!create_test_file(test_file)) return; memset(&mmio, 0, sizeof(mmio)); mmio.fccIOProc = FOURCC_DOS; mmio.pchBuffer = buffer; mmio.cchBuffer = sizeof(buffer); hmmio = mmioOpen(test_file, &mmio, MMIO_READ); ok(hmmio != NULL, "mmioOpen error %u\n", mmio.wErrorRet); if (hmmio == NULL) { DeleteFileA(test_file); return; } ret = mmioSeek(hmmio, 0, SEEK_END); ok(sizeof(RIFF_buf) == ret, "got %d\n", ret); ret = mmioRead(hmmio, data, sizeof(data)); ok(ret == 0, "expected %d, got %d\n", 0, ret); res = mmioGetInfo(hmmio, &mmio, 0); ok(res == MMSYSERR_NOERROR, "expected 0, got %d\n", res); res = mmioAdvance(hmmio, &mmio, MMIO_READ); ok(res == MMSYSERR_NOERROR, "expected 0, got %d\n", res); ok(mmio.pchNext == mmio.pchEndRead, "expected %p, got %p\n", mmio.pchEndRead, mmio.pchNext); mmioClose(hmmio, 0); DeleteFileA(test_file); }
/** 読み込み * * @author SAM (T&GG, Org.)<*****@*****.**> * @date 2004/01/21 3:20:24 * Copyright (C) 2001,2002,2003,2004 SAM (T&GG, Org.). All rights reserved. */ HRslt WavFile::read( void *dst, size_t size, size_t * const readsize ) { if( !hmmio_ ) return CO_E_NOTINITIALIZED; if( !dst ) return E_INVALIDARG; if( readsize ) *readsize = 0; MMIOINFO mmioinfo; // current status of hmmio_ if( 0 != mmioGetInfo( hmmio_, &mmioinfo, 0 ) ) return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL ); DWORD cbDataIn = (DWORD)size; if( cbDataIn > ck_.cksize ) cbDataIn = ck_.cksize; ck_.cksize -= cbDataIn; for( size_t cT = 0; cT < cbDataIn; cT++ ) { // Copy the bytes from the io to the buffer. if( mmioinfo.pchNext == mmioinfo.pchEndRead ) { if( 0 != mmioAdvance( hmmio_, &mmioinfo, MMIO_READ ) ) return DXTRACE_ERR( TEXT("mmioAdvance"), E_FAIL ); if( mmioinfo.pchNext == mmioinfo.pchEndRead ) return DXTRACE_ERR( TEXT("mmioinfo.pchNext"), E_FAIL ); } // Actual copy. *((uint8_t *)dst+cT) = *mmioinfo.pchNext; mmioinfo.pchNext++; } if( 0 != mmioSetInfo( hmmio_, &mmioinfo, 0 ) ) return DXTRACE_ERR( TEXT("mmioSetInfo"), E_FAIL ); if( readsize ) *readsize = cbDataIn; return S_OK; }
//----------------------------------------------------------------------------- // Name: CWaveFile::Read() // Desc: Reads section of data from a wave file into pBuffer and returns // how much read in pdwSizeRead, reading not more than dwSizeToRead. // This uses m_ck to determine where to start reading from. So // subsequent calls will be continue where the last left off unless // Reset() is called. //----------------------------------------------------------------------------- HRESULT CWaveFile::Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead ) { if( m_bIsReadingFromMemory ) { if( m_pbDataCur == NULL ) return CO_E_NOTINITIALIZED; if( pdwSizeRead != NULL ) *pdwSizeRead = 0; if( (BYTE*)(m_pbDataCur + dwSizeToRead) > (BYTE*)(m_pbData + m_ulDataSize) ) { dwSizeToRead = m_ulDataSize - (DWORD)(m_pbDataCur - m_pbData); } CopyMemory( pBuffer, m_pbDataCur, dwSizeToRead ); if( pdwSizeRead != NULL ) *pdwSizeRead = dwSizeToRead; return S_OK; } else { MMIOINFO mmioinfoIn; // current status of m_hmmio if( m_hmmio == NULL ) return CO_E_NOTINITIALIZED; if( pBuffer == NULL || pdwSizeRead == NULL ) return E_INVALIDARG; if( pdwSizeRead != NULL ) *pdwSizeRead = 0; if( 0 != mmioGetInfo( m_hmmio, &mmioinfoIn, 0 ) ) return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL ); UINT cbDataIn = dwSizeToRead; if( cbDataIn > m_ck.cksize ) cbDataIn = m_ck.cksize; m_ck.cksize -= cbDataIn; for( DWORD cT = 0; cT < cbDataIn; cT++ ) { // Copy the bytes from the io to the buffer. if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) { if( 0 != mmioAdvance( m_hmmio, &mmioinfoIn, MMIO_READ ) ) return DXTRACE_ERR( TEXT("mmioAdvance"), E_FAIL ); if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) return DXTRACE_ERR( TEXT("mmioinfoIn.pchNext"), E_FAIL ); } // Actual copy. *((BYTE*)pBuffer+cT) = *((BYTE*)mmioinfoIn.pchNext); mmioinfoIn.pchNext++; } if( 0 != mmioSetInfo( m_hmmio, &mmioinfoIn, 0 ) ) return DXTRACE_ERR( TEXT("mmioSetInfo"), E_FAIL ); if( pdwSizeRead != NULL ) *pdwSizeRead = cbDataIn; return S_OK; } }
static void test_mmio_buffer_pointer(void) { char test_file[MAX_PATH]; char buffer[5], data[16]; MMIOINFO mmio; HMMIO hmmio; LONG size, pos; MMRESULT res; if (!create_test_file(test_file)) return; memset(&mmio, 0, sizeof(mmio)); mmio.fccIOProc = FOURCC_DOS; mmio.pchBuffer = buffer; mmio.cchBuffer = sizeof(buffer); hmmio = mmioOpen(test_file, &mmio, MMIO_READ); ok(hmmio != NULL, "mmioOpen error %u\n", mmio.wErrorRet); if (hmmio == NULL) { DeleteFileA(test_file); return; } /* the buffer is empty */ size = mmioRead(hmmio, data, 0); ok(size == 0, "expected 0, got %d\n", size); res = mmioGetInfo(hmmio, &mmio, 0); ok(res == MMSYSERR_NOERROR, "expected 0, got %d\n", res); ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead); /* fill the buffer */ size = mmioAdvance(hmmio, &mmio, MMIO_READ); ok(mmio.pchEndRead-mmio.pchBuffer == sizeof(buffer), "got %d\n", (int)(mmio.pchEndRead-mmio.pchBuffer)); /* seeking to the same buffer chunk, the buffer is kept */ size = sizeof(buffer)/2; pos = mmioSeek(hmmio, size, SEEK_SET); ok(pos == size, "failed to seek, expected %d, got %d\n", size, pos); res = mmioGetInfo(hmmio, &mmio, 0); ok(res == MMSYSERR_NOERROR, "expected 0, got %d\n", res); ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset); ok(mmio.pchNext-mmio.pchBuffer == size, "expected %d, got %d\n", size, (int)(mmio.pchNext-mmio.pchBuffer)); ok(mmio.pchEndRead-mmio.pchBuffer == sizeof(buffer), "got %d\n", (int)(mmio.pchEndRead-mmio.pchBuffer)); /* seeking to another buffer chunk, the buffer is empty */ size = sizeof(buffer) * 3 + sizeof(buffer) / 2; pos = mmioSeek(hmmio, size, SEEK_SET); ok(pos == size, "failed to seek, got %d\n", pos); res = mmioGetInfo(hmmio, &mmio, 0); ok(res == MMSYSERR_NOERROR, "expected 0, got %d\n", res); ok(mmio.lBufOffset == size, "expected %d, got %d\n", size, mmio.lBufOffset); ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext); ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead); /* reading a lot (as sizeof(data) > mmio.cchBuffer), the buffer is empty */ size = mmioRead(hmmio, data, sizeof(data)); ok(size == sizeof(data), "failed to read, got %d\n", size); res = mmioGetInfo(hmmio, &mmio, 0); ok(res == MMSYSERR_NOERROR, "expected 0, got %d\n", res); ok(mmio.lBufOffset == pos+size, "expected %d, got %d\n", pos+size, mmio.lBufOffset); ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext); ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead); mmioClose(hmmio, 0); DeleteFileA(test_file); }
PSOUNDINSTANCE CreateSoundInstance(PSOUND sound) { UINT nextFree = g_nextFreeInstance; if (nextFree < MAX_SOUND_INSTANCES) { MMRESULT mr = 0; PSOUNDINSTANCE instance = &g_soundInstances[nextFree]; instance->Volume = DEFAULT_VOLUME_VALUE; instance->Sound = sound; instance->Header = (LPWAVEHDR)malloc(sizeof(WAVEHDR)); ZeroMemory(instance->Header, sizeof(WAVEHDR)); if (sound->IsMusic) { DWORD current; PSTREAMINFO stream = sound->Stream; instance->Header->lpData = (LPSTR)malloc(g_streamChunkSize); instance->Header->dwBufferLength = g_streamChunkSize; mr = mmioGetInfo(stream->Stream, &stream->StreamInfo, 0); for (current = 0; current < g_streamChunkSize && mr == MMSYSERR_NOERROR; ++current) { if (stream->StreamInfo.pchNext == stream->StreamInfo.pchEndRead) { mr = mmioAdvance(stream->Stream, &stream->StreamInfo, MMIO_READ); if (mr == MMSYSERR_NOERROR) { mr = (stream->StreamInfo.pchNext != stream->StreamInfo.pchEndRead ? MMSYSERR_NOERROR : MMSYSERR_ERROR); } } if (mr == MMSYSERR_NOERROR) { instance->Header->lpData[current] = *stream->StreamInfo.pchNext; ++stream->StreamInfo.pchNext; } } } else { /* sound fx */ /* first shallow copy the top level header */ memcpy(instance->Header, sound->Data, sizeof(WAVEHDR)); /* then alloc and copy data */ instance->Header->lpData = (LPSTR)malloc(sound->Data->dwBufferLength); memcpy(instance->Header->lpData, sound->Data->lpData, sound->Data->dwBufferLength); } if (mr == 0) { if (waveOutGetNumDevs() > 0) { mr = waveOutOpen(&instance->WaveOut, 0, &sound->Format, (DWORD_PTR)WaveOutProc, (DWORD_PTR)instance, CALLBACK_FUNCTION | WAVE_MAPPED); } } if (mr == 0) { ++g_nextFreeInstance; for (; g_nextFreeInstance < MAX_SOUND_INSTANCES; ++g_nextFreeInstance) { if (!g_soundInstances[g_nextFreeInstance].WaveOut) { break; } } waveOutPrepareHeader(instance->WaveOut, instance->Header, sizeof(WAVEHDR)); return instance; } else { free(instance->Header->lpData); free(instance->Header); ZeroMemory(instance, sizeof(SOUNDINSTANCE)); } } return NULL; }
BOOL CreateSoundFromWave(PSOUND sound, PSTR waveFile, BOOL music) { MMRESULT mr = MMSYSERR_ERROR; HMMIO hmmio = NULL; ZeroMemory(sound, sizeof(SOUND)); hmmio = mmioOpen(waveFile, NULL, MMIO_ALLOCBUF | MMIO_READ); if (hmmio != NULL) { MMCKINFO riff = {0}; MMCKINFO chunk = {0}; PCMWAVEFORMAT pcmFormat = {0}; mr = mmioDescend(hmmio, &riff, NULL, 0); if (mr == 0) { /* ensure it's a proper wave file */ if (riff.ckid != FOURCC_RIFF || riff.fccType != mmioFOURCC('W', 'A', 'V', 'E')) { mr = MMSYSERR_ERROR; } } if (mr == 0) { /* find the format info */ chunk.ckid = mmioFOURCC( 'f', 'm', 't', ' ' ); if (mmioDescend(hmmio, &chunk, &riff, MMIO_FINDCHUNK) == 0) { if (mmioRead(hmmio, (HPSTR)&pcmFormat, sizeof(PCMWAVEFORMAT)) == sizeof(PCMWAVEFORMAT) && pcmFormat.wf.wFormatTag == WAVE_FORMAT_PCM) { memcpy(&sound->Format, &pcmFormat, sizeof(pcmFormat)); sound->Format.cbSize = 0; } else { mr = MMSYSERR_ERROR; } } else { mr = MMSYSERR_ERROR; } } if (mr == 0) { /* find the data chunk */ if (mmioSeek(hmmio, riff.dwDataOffset + sizeof(FOURCC), SEEK_SET) != -1) { chunk.ckid = mmioFOURCC('d', 'a', 't', 'a'); mr = mmioDescend(hmmio, &chunk, &riff, MMIO_FINDCHUNK); } else { mr = MMSYSERR_ERROR; } } if (mr == 0) { if (music) { /* if this is music, store off the streaming info and stop */ sound->IsMusic = TRUE; sound->Stream = (PSTREAMINFO)malloc(sizeof(STREAMINFO)); sound->Stream->Playing = FALSE; sound->Stream->Stream = hmmio; sound->Stream->TotalSize = chunk.cksize; sound->Stream->Riff = riff; sound->Stream->UsedSize = 0; mr = mmioGetInfo(hmmio, &sound->Stream->StreamInfo, 0); } else { /* if this is sound fx, then copy the buffer to the sound object so we can tear off instances */ MMIOINFO info = {0}; DWORD current; DWORD size = chunk.cksize; sound->IsMusic = FALSE; sound->Data = (LPWAVEHDR)malloc(sizeof(WAVEHDR)); ZeroMemory(sound->Data, sizeof(WAVEHDR)); mr = mmioGetInfo(hmmio, &info, 0); sound->Data->lpData = (LPSTR)malloc(size); sound->Data->dwBufferLength = size; for (current = 0; current < size && mr == MMSYSERR_NOERROR; ++current) { if (info.pchNext == info.pchEndRead) { mr = mmioAdvance(hmmio, &info, MMIO_READ); if (mr == MMSYSERR_NOERROR) { mr = (info.pchNext != info.pchEndRead ? MMSYSERR_NOERROR : MMSYSERR_ERROR); } } if (mr == MMSYSERR_NOERROR) { sound->Data->lpData[current] = *info.pchNext; ++info.pchNext; } } } } } if (mr == 0) { if (!music) { mmioClose(hmmio, 0); } return TRUE; } else { /* clean up any stank */ DestroySound(sound); if (hmmio) { mmioClose(hmmio, 0); } return FALSE; } }
VOID CALLBACK WaveOutProc(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) { USHORT i; switch (uMsg) { case WOM_DONE: { LPWAVEHDR header = (LPWAVEHDR)dwParam1; PSOUNDINSTANCE instance = (PSOUNDINSTANCE)dwInstance; assert(instance->Header == header); if (instance->Sound->IsMusic) { /* need to continue the stream */ DWORD remaining; PSTREAMINFO streamInfo = instance->Sound->Stream; /* cleanup current chunk */ waveOutUnprepareHeader(instance->WaveOut, instance->Header, sizeof(WAVEHDR)); /* is there more to play? */ remaining = streamInfo->TotalSize - streamInfo->UsedSize; if (remaining > 0) { MMRESULT mr = 0; DWORD current, size; size = min(g_streamChunkSize, remaining); streamInfo->UsedSize += size; instance->Header->dwBufferLength = size; for (current = 0; current < size && mr == MMSYSERR_NOERROR; ++current) { if (streamInfo->StreamInfo.pchNext == streamInfo->StreamInfo.pchEndRead) { mr = mmioAdvance(streamInfo->Stream, &streamInfo->StreamInfo, MMIO_READ); if (mr == MMSYSERR_NOERROR) { mr = (streamInfo->StreamInfo.pchNext != streamInfo->StreamInfo.pchEndRead ? MMSYSERR_NOERROR : MMSYSERR_ERROR); } } if (mr == MMSYSERR_NOERROR) { instance->Header->lpData[current] = *streamInfo->StreamInfo.pchNext; ++streamInfo->StreamInfo.pchNext; } } /* ensure header is ready, and start playing next chunk */ waveOutPrepareHeader(instance->WaveOut, instance->Header, sizeof(WAVEHDR)); waveOutSetVolume(instance->WaveOut, instance->Volume); waveOutWrite(instance->WaveOut, instance->Header, sizeof(WAVEHDR)); } else { /* TODO: Should music always loop? or should we add a flag for it? */ streamInfo->Playing = FALSE; streamInfo->UsedSize = 0; AddInstanceToDestroyQueue(instance); } } else { /* sound fx instances should get cleaned up */ AddInstanceToDestroyQueue(instance); } } break; } }
//----------------------------------------------------------------------------- // Name: CWaveFile::Read() // Desc: Reads section of data from a wave file into pBuffer and returns // how much read in pdwSizeRead, reading not more than dwSizeToRead. // This uses m_ck to determine where to start reading from. So // subsequent calls will be continue where the last left off unless // Reset() is called. //----------------------------------------------------------------------------- HRESULT CWaveFile::Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead ) { if( m_bIsReadingFromMemory ) { if( m_pbDataCur == NULL ) return CO_E_NOTINITIALIZED; if( pdwSizeRead != NULL ) *pdwSizeRead = 0; if( ( BYTE* )( m_pbDataCur + dwSizeToRead ) > ( BYTE* )( m_pbData + m_ulDataSize ) ) { dwSizeToRead = m_ulDataSize - ( DWORD )( m_pbDataCur - m_pbData ); } #pragma warning( disable: 4616 ) // disable warning about warning number '22104' being out of range #pragma warning( disable: 22104 ) // disable PREfast warning during static code analysis CopyMemory( pBuffer, m_pbDataCur, dwSizeToRead ); #pragma warning( default: 22104 ) #pragma warning( default: 4616 ) if( pdwSizeRead != NULL ) *pdwSizeRead = dwSizeToRead; return S_OK; } else { MMIOINFO mmioinfoIn; // current status of m_hmmio if( m_hmmio == NULL ) return CO_E_NOTINITIALIZED; if( pBuffer == NULL || pdwSizeRead == NULL ) return E_INVALIDARG; *pdwSizeRead = 0; if( 0 != mmioGetInfo( m_hmmio, &mmioinfoIn, 0 ) ) return DXTRACE_ERR( L"mmioGetInfo", E_FAIL ); UINT cbDataIn = dwSizeToRead; if( cbDataIn > m_ck.cksize ) cbDataIn = m_ck.cksize; m_ck.cksize -= cbDataIn; for( DWORD cT = 0; cT < cbDataIn; cT++ ) { // Copy the bytes from the io to the buffer. if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) { if( 0 != mmioAdvance( m_hmmio, &mmioinfoIn, MMIO_READ ) ) return DXTRACE_ERR( L"mmioAdvance", E_FAIL ); if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) return DXTRACE_ERR( L"mmioinfoIn.pchNext", E_FAIL ); } // Actual copy. *( ( BYTE* )pBuffer + cT ) = *( ( BYTE* )mmioinfoIn.pchNext ); mmioinfoIn.pchNext++; } if( 0 != mmioSetInfo( m_hmmio, &mmioinfoIn, 0 ) ) return DXTRACE_ERR( L"mmioSetInfo", E_FAIL ); *pdwSizeRead = cbDataIn; return S_OK; } }
int SoundEvent::PlaySound(char *filenames,int newbuffer, double offset) { HMMIO m_hmmio; HRESULT hr; TRACESETUP("PLAYSOUND"); if(newbuffer) { m_hmmio = mmioOpen( filenames, NULL, MMIO_ALLOCBUF | MMIO_READ ); if( NULL == m_hmmio ) { TRACE ("DIRECT SOUND ERROR MMIOOPEN"); return (false); } MMCKINFO ckIn; // chunk info. for general use. PCMWAVEFORMAT pcmWaveFormat; // Temp PCM structure to load in. WAVEFORMATEX* m_pwfx; // Pointer to WAVEFORMATEX structure MMCKINFO m_ck; // Multimedia RIFF chunk MMCKINFO m_ckRiff; // Use in opening a WAVE file DWORD m_dwSize; // The size of the wave file MMIOINFO m_mmioinfoOut; DWORD m_dwFlags; #define WAVEFILE_READ 1 #define WAVEFILE_WRITE 2 m_pwfx = NULL; if( ( 0 != mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) ) ) { TRACE ("DIRECT SOUND ERROR MMIODESCEND"); return (false); } // Check to make sure this is a valid wave file if( (m_ckRiff.ckid != FOURCC_RIFF) || (m_ckRiff.fccType != mmioFOURCC('W', 'A', 'V', 'E') ) ) { return(false); TRACE ("DIRECT SOUND ERROR MMIOFOURCC"); } // Search the input file for for the 'fmt ' chunk. ckIn.ckid = mmioFOURCC('f', 'm', 't', ' '); if( 0 != mmioDescend( m_hmmio, &ckIn, &m_ckRiff, MMIO_FINDCHUNK ) ) { TRACE("DIRECT SOUND ERROR MMIDESCENT FIND CHUNK"); return(false); } // Expect the 'fmt' chunk to be at least as large as <PCMWAVEFORMAT>; // if there are extra parameters at the end, we'll ignore them if( ckIn.cksize < (LONG) sizeof(PCMWAVEFORMAT) ) { TRACE ("DIRECT SOUND ERROR CHUNKSIZE"); return(false); } // Read the 'fmt ' chunk into <pcmWaveFormat>. if( mmioRead( m_hmmio, (HPSTR) &pcmWaveFormat, sizeof(pcmWaveFormat)) != sizeof(pcmWaveFormat) ) { TRACE ("DIRECT SOUND ERROR MMIOREAD"); return(false); } // Allocate the waveformatex, but if its not pcm format, read the next // word, and thats how many extra bytes to allocate. if( pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM ) { m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) ]; if( NULL == m_pwfx ) { TRACE("DIRECT SOUND ERROR ALLOC"); return(false); } // Copy the bytes from the pcm structure to the waveformatex structure memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) ); m_pwfx->cbSize = 0; } else { // Read in length of extra bytes. WORD cbExtraBytes = 0L; if( mmioRead( m_hmmio, (CHAR*)&cbExtraBytes, sizeof(WORD)) != sizeof(WORD) ) { TRACE ("DIRECT SOUND ERROR M_HMMIO"); return(false); } m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) + cbExtraBytes ]; if( NULL == m_pwfx ) { TRACE("DIRECT SOUND ERREOR ALLOC 2"); return(false); } // Copy the bytes from the pcm structure to the waveformatex structure memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) ); m_pwfx->cbSize = cbExtraBytes; // Now, read those extra bytes into the structure, if cbExtraAlloc != 0. if( mmioRead( m_hmmio, (CHAR*)(((BYTE*)&(m_pwfx->cbSize))+sizeof(WORD)), cbExtraBytes ) != cbExtraBytes ) { //SAFE_DELETE( m_pwfx ); TRACE("DIRECT SOUND ERROR MMIOREAD2"); return(false); } } // Ascend the input file out of the 'fmt ' chunk. if( 0 != mmioAscend( m_hmmio, &ckIn, 0 ) ) { //SAFE_DELETE( m_pwfx ); TRACE("DIRECT SOUND ERROR MMIOASCEND"); return(false); } TRACE("DIRECTSOUND READMMIO OK"); m_dwFlags = WAVEFILE_READ; if( m_dwFlags == WAVEFILE_READ ) { // Seek to the data if( -1 == mmioSeek( m_hmmio, m_ckRiff.dwDataOffset + sizeof(FOURCC), SEEK_SET ) ) { TRACE ("DIRECT SOUND ERROR MMIOSEEK"); return(false); } // Search the input file for the 'data' chunk. m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a'); if( 0 != mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ) { TRACE ("DIRECT SOUND ERROR MMIODESCEND"); return(false); } } else { // Create the 'data' chunk that holds the waveform samples. m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a'); m_ck.cksize = 0; if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) ) { TRACE("DIRECT SOUND ERROR MMIOCREATECHUNK"); return(false); } if( 0 != mmioGetInfo( m_hmmio, &m_mmioinfoOut, 0 ) ) { TRACE ("DIRECT SOUND ERROR MMMIOGETINFO"); return(false); } } TRACE("DIRECTSOUND RESETFILE OK"); // After the reset, the size of the wav file is m_ck.cksize so store it now m_dwSize = m_ck.cksize; char buffers[80]; TRACE ("DIRECTSOUND TAILLE BUFFER"); sprintf(buffers,"%d", m_dwSize); TRACE (buffers); DWORD dwDSBufferSize = NULL; apDSBuffer = new LPDIRECTSOUNDBUFFER[1]; if( apDSBuffer == NULL ) { TRACE("ERROR DIRECTSOUND NEW BUFFER"); return(false); } // Make the DirectSound buffer the same size as the wav file dwDSBufferSize = m_dwSize; // Create the direct sound buffer, and only request the flags needed // since each requires some overhead and limits if the buffer can // be hardware accelerated DSBUFFERDESC dsbd2; ZeroMemory( &dsbd2, sizeof(DSBUFFERDESC) ); dsbd2.dwSize = sizeof(DSBUFFERDESC); dsbd2.dwFlags = 0; dsbd2.dwBufferBytes = dwDSBufferSize; dsbd2.guid3DAlgorithm = GUID_NULL; dsbd2.lpwfxFormat = m_pwfx; TRACE ("APPEL CREATE SOUND BUFFER"); // DirectSound is only guarenteed to play PCM data. Other // formats may or may not work depending the sound card driver. hr = m_pDS->CreateSoundBuffer( &dsbd2, &apDSBuffer[0], NULL ); if (hr != DS_OK) TRACE ("ERROR DIRECTSOUND CREATE SOUND BUFFER") else TRACE("DIRECTSOUND CREATE SOUND BUFFER OK"); // Make sure we have focus, and we didn't just switch in from // an app which had a DirectSound device // hr = RestoreBuffer( &apDSBuffer[0], NULL ); // if (hr != DS_OK) // TRACE ("ERROR DIRECTSOUND RESTORE SOUND BUFFER") // else TRACE("DIRECTSOUND RESTORE SOUND BUFFER OK"); // Lock the buffer down hr = apDSBuffer[0]->Lock( 0, m_dwSize, &pDSLockedBuffer, &dwDSLockedBufferSize, NULL, NULL, 0L ); if (hr != DS_OK) TRACE ("ERROR DIRECTSOUND LOCK") else TRACE ("DIRECTSOUND LOCK OK"); // Reset the wave file to the beginning // Seek to the data if( -1 == mmioSeek( m_hmmio, m_ckRiff.dwDataOffset + sizeof(FOURCC), SEEK_SET ) ) TRACE ("ERROR DIRECTSOUND MMIOSEEK") else TRACE ("DIRECTSOUND MMIOSSEEK OK"); // Search the input file for the 'data' chunk. m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a'); if( 0 != mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ) TRACE ("ERROR DIRECTSOUND MMIODESCEND") else TRACE ("DIRECTSOUND MMIODESCEND OK"); MMIOINFO mmioinfoIn; // current status of m_hmmio DWORD dwWavDataRead = 0; // Amount of data read from the wav file dwWavDataRead = 0; if( 0 != mmioGetInfo( m_hmmio, &mmioinfoIn, 0 ) ) TRACE ("ERROR DIRECTSOUND MMIOGETINFO") else TRACE ("DIRECTSOUND MMIOGETINFO OK"); UINT cbDataIn = m_dwSize; if( cbDataIn > m_ck.cksize ) cbDataIn = m_ck.cksize; m_ck.cksize -= cbDataIn; for( DWORD cT = 0; cT < cbDataIn; cT++ ) { // Copy the bytes from the io to the buffer. if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) { if( 0 != mmioAdvance( m_hmmio, &mmioinfoIn, MMIO_READ ) ) TRACE ("ERROR DIRECTSOUND MMIOADVANCE") else /* TRACE ("DIRECTSOUND MMIOADVANCE OK")*/; if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) TRACE ("ERROR DIRECTSOUND READ FIC") else /* TRACE ("DIRECTSOUND READ FIC OK") */; } // Actual copy. *((BYTE*)pDSLockedBuffer+cT) = *((BYTE*)mmioinfoIn.pchNext); mmioinfoIn.pchNext++; } if( 0 != mmioSetInfo( m_hmmio, &mmioinfoIn, 0 ) ) TRACE ("ERROR DIRECTSOUND MMIOSETINFO") else TRACE ("DIRECTSOUND MMIOSETINFO OK"); mmioClose( m_hmmio, 0 ); dwWavDataRead = cbDataIn; } // end of newbuffer part // Unlock the buffer, we don't need it anymore. // apDSBuffer[0]->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); if (offset > 0.) { DWORD curplay,curwrite; char buffers[80]; apDSBuffer[0]->GetCurrentPosition(&curplay,&curwrite); sprintf(buffers, "POS CURPLAY AVT %d", curplay); TRACE(buffers); curplay = DWORD (offset * 8000.); hr = apDSBuffer[0]->SetCurrentPosition(curplay); if (hr != DS_OK) TRACE ("ERROR DIRECTSOUND SETCURRENT") else TRACE ("DIRECTSOUND SETCURRENT OK"); apDSBuffer[0]->GetCurrentPosition(&curplay,&curwrite); sprintf(buffers, "POS CURPLAY APS %d", curplay); TRACE(buffers); }