HRESULT WaveDecoder::ResetFile() { if( m_hmmio == NULL ) return CO_E_NOTINITIALIZED; if( m_dwFlags == WAVEFILE_READ ) { // Seek to the data if( -1 == mmioSeek( m_hmmio, m_ckRiff.dwDataOffset + sizeof( FOURCC ), SEEK_SET ) ) return E_FAIL; // 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 ) ) return E_FAIL; } 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 ) ) return E_FAIL; if( 0 != mmioGetInfo( m_hmmio, &m_mmioinfoOut, 0 ) ) return E_FAIL; } return S_OK; }
int WaveStartDataRead( HMMIO *phmmioIn, MMCKINFO *pckIn, MMCKINFO *pckInRIFF ) { int nError; nError = 0; // Do a nice little seek... if ((nError = mmioSeek(*phmmioIn, pckInRIFF->dwDataOffset + sizeof(FOURCC), SEEK_SET)) == -1) { _ASSERT(FALSE); } nError = 0; // Search the input file for for the 'data' chunk. pckIn->ckid = mmioFOURCC('d', 'a', 't', 'a'); if ((nError = mmioDescend(*phmmioIn, pckIn, pckInRIFF, MMIO_FINDCHUNK)) != 0) { goto ERROR_READING_WAVE; } goto CLEANUP; ERROR_READING_WAVE: CLEANUP: return(nError); }
// Cue // BOOL WaveFile::Cue (void) { BOOL fRtn = SUCCESS; // assume success DOUT ("WaveFile::Cue\n\r"); // Seek to 'data' chunk from beginning of file if (mmioSeek (m_hmmio, m_mmckiRiff.dwDataOffset + sizeof(FOURCC), SEEK_SET) != -1) { // Descend into 'data' chunk m_mmckiData.ckid = mmioFOURCC('d', 'a', 't', 'a'); if ((m_mmr = mmioDescend (m_hmmio, &m_mmckiData, &m_mmckiRiff, MMIO_FINDCHUNK)) == MMSYSERR_NOERROR) { // Reset byte counter m_nBytesPlayed = 0; } else { // UNDONE: set m_mmr fRtn = FALSE; } } else { // mmioSeek error m_mmr = MMIOERR_CANNOTSEEK; fRtn = FALSE; } return fRtn; }
static BOOL MCIAVI_GetInfoAudio(WINE_MCIAVI* wma, const MMCKINFO* mmckList, MMCKINFO *mmckStream) { MMCKINFO mmckInfo; TRACE("ash.fccType='%c%c%c%c'\n", LOBYTE(LOWORD(wma->ash_audio.fccType)), HIBYTE(LOWORD(wma->ash_audio.fccType)), LOBYTE(HIWORD(wma->ash_audio.fccType)), HIBYTE(HIWORD(wma->ash_audio.fccType))); if (wma->ash_audio.fccHandler) /* not all streams specify a handler */ TRACE("ash.fccHandler='%c%c%c%c'\n", LOBYTE(LOWORD(wma->ash_audio.fccHandler)), HIBYTE(LOWORD(wma->ash_audio.fccHandler)), LOBYTE(HIWORD(wma->ash_audio.fccHandler)), HIBYTE(HIWORD(wma->ash_audio.fccHandler))); else TRACE("ash.fccHandler=0, no handler specified\n"); TRACE("ash.dwFlags=%d\n", wma->ash_audio.dwFlags); TRACE("ash.wPriority=%d\n", wma->ash_audio.wPriority); TRACE("ash.wLanguage=%d\n", wma->ash_audio.wLanguage); TRACE("ash.dwInitialFrames=%d\n", wma->ash_audio.dwInitialFrames); TRACE("ash.dwScale=%d\n", wma->ash_audio.dwScale); TRACE("ash.dwRate=%d\n", wma->ash_audio.dwRate); TRACE("ash.dwStart=%d\n", wma->ash_audio.dwStart); TRACE("ash.dwLength=%d\n", wma->ash_audio.dwLength); TRACE("ash.dwSuggestedBufferSize=%d\n", wma->ash_audio.dwSuggestedBufferSize); TRACE("ash.dwQuality=%d\n", wma->ash_audio.dwQuality); TRACE("ash.dwSampleSize=%d\n", wma->ash_audio.dwSampleSize); TRACE("ash.rcFrame=(%d,%d,%d,%d)\n", wma->ash_audio.rcFrame.top, wma->ash_audio.rcFrame.left, wma->ash_audio.rcFrame.bottom, wma->ash_audio.rcFrame.right); /* rewind to the start of the stream */ mmioAscend(wma->hFile, mmckStream, 0); mmckInfo.ckid = ckidSTREAMFORMAT; if (mmioDescend(wma->hFile, &mmckInfo, mmckList, MMIO_FINDCHUNK) != 0) { WARN("Can't find 'strf' chunk\n"); return FALSE; } if (mmckInfo.cksize < sizeof(WAVEFORMAT)) { WARN("Size of strf chunk (%d) < audio format struct\n", mmckInfo.cksize); return FALSE; } wma->lpWaveFormat = HeapAlloc(GetProcessHeap(), 0, mmckInfo.cksize); if (!wma->lpWaveFormat) { WARN("Can't alloc WaveFormat\n"); return FALSE; } mmioRead(wma->hFile, (LPSTR)wma->lpWaveFormat, mmckInfo.cksize); TRACE("waveFormat.wFormatTag=%d\n", wma->lpWaveFormat->wFormatTag); TRACE("waveFormat.nChannels=%d\n", wma->lpWaveFormat->nChannels); TRACE("waveFormat.nSamplesPerSec=%d\n", wma->lpWaveFormat->nSamplesPerSec); TRACE("waveFormat.nAvgBytesPerSec=%d\n", wma->lpWaveFormat->nAvgBytesPerSec); TRACE("waveFormat.nBlockAlign=%d\n", wma->lpWaveFormat->nBlockAlign); TRACE("waveFormat.wBitsPerSample=%d\n", wma->lpWaveFormat->wBitsPerSample); if (mmckInfo.cksize >= sizeof(WAVEFORMATEX)) TRACE("waveFormat.cbSize=%d\n", wma->lpWaveFormat->cbSize); return TRUE; }
/** カーソルを巻き戻す * * @author SAM (T&GG, Org.)<*****@*****.**> * @date 2004/01/21 3:08:18 * Copyright (C) 2001,2002,2003,2004 SAM (T&GG, Org.). All rights reserved. */ HRslt WavFile::rewind() { if(!hmmio_) return CO_E_NOTINITIALIZED; if( flags_&READ ) { // Seek to the data if( -1 == mmioSeek( hmmio_, ckriff_.dwDataOffset + sizeof(FOURCC), SEEK_SET ) ) return DXTRACE_ERR( TEXT("mmioSeek"), E_FAIL ); // Search the input file for the 'data' chunk. ck_.ckid = mmioFOURCC('d','a','t','a'); if( 0 != mmioDescend( hmmio_, &ck_, &ckriff_, MMIO_FINDCHUNK ) ) return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); } else { // Create the 'data' chunk that holds the waveform samples. ck_.ckid = mmioFOURCC('d','a','t','a'); ck_.cksize = 0; if( 0 != mmioCreateChunk( hmmio_, &ck_, 0 ) ) return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); if( 0 != mmioGetInfo( hmmio_, &write_mmioinfo_, 0 ) ) return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL ); } return S_OK; }
DWORD CMmio::DescendList (FOURCC chunk) { ASSERT (m_hMmio != NULL); ASSERT_VALID (this); if (m_iListDepth >= MMIO_NUM_LIST) { ThrowError (ERR_MMIO_DESCEND_LIST); } MMCKINFO * pMckiPar; if (m_iListDepth == 0) pMckiPar = &m_mckiRiff; else pMckiPar = &m_mckiList[m_iListDepth-1]; memset (&m_mckiList[m_iListDepth], 0, sizeof (MMCKINFO)); m_mckiList[m_iListDepth].ckid = mmioFOURCC ('L', 'I', 'S', 'T'); m_mckiList[m_iListDepth].fccType = chunk; if (mmioDescend (m_hMmio, &m_mckiList[m_iListDepth], pMckiPar, MMIO_FINDLIST) != 0) { ThrowError (ERR_MMIO_DESCEND_LIST); } m_iListDepth++; return (m_mckiList[m_iListDepth-1].cksize); }
/** ストリームを閉じる * * @author SAM (T&GG, Org.)<*****@*****.**> * @date 2004/01/21 3:32:04 * Copyright (C) 2001,2002,2003,2004 SAM (T&GG, Org.). All rights reserved. */ HRslt WavFile::close() { if( !hmmio_ ) return CO_E_NOTINITIALIZED; if( flags_ & READ ) { mmioClose( hmmio_, 0 ); hmmio_ = NULL; } else { write_mmioinfo_.dwFlags |= MMIO_DIRTY; if( 0 != mmioSetInfo( hmmio_, &write_mmioinfo_, 0 ) ) return DXTRACE_ERR( TEXT("mmioSetInfo"), E_FAIL ); // Ascend the output file out of the 'data' chunk -- this will cause // the chunk size of the 'data' chunk to be written. if( 0 != mmioAscend( hmmio_, &ck_, 0 ) ) return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); // Do this here instead... if( 0 != mmioAscend( hmmio_, &ckriff_, 0 ) ) return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); mmioSeek( hmmio_, 0, SEEK_SET ); if( 0 != (int)mmioDescend( hmmio_, &ckriff_, NULL, 0 ) ) return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); ck_.ckid = mmioFOURCC('f','a','c','t'); if( 0 == mmioDescend( hmmio_, &ck_, &ckriff_, MMIO_FINDCHUNK ) ) { DWORD dwSamples = 0; mmioWrite( hmmio_, (HPSTR)&dwSamples, sizeof(dwSamples) ); mmioAscend( hmmio_, &ck_, 0 ); } // Ascend the output file out of the 'RIFF' chunk -- this will cause // the chunk size of the 'RIFF' chunk to be written. if( 0 != mmioAscend( hmmio_, &ckriff_, 0 ) ) return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); mmioClose( hmmio_, 0 ); hmmio_ = NULL; } SAFE_FREE( buffer_ ); SAFE_FREE( wfx_ ); return S_OK; }
//----------------------------------------------------------------------------- // Name: WaveCloseWriteFile() // Desc: This routine will close a wave file used for writing. //----------------------------------------------------------------------------- HRESULT WaveCloseWriteFile( HMMIO hmmioOut, MMCKINFO *pckOut, MMCKINFO *pckOutRIFF, MMIOINFO *pmmioinfoOut, DWORD dwSamples ) { pmmioinfoOut->dwFlags |= MMIO_DIRTY; if( 0 != mmioSetInfo( hmmioOut, pmmioinfoOut, 0 ) ) return E_FAIL; // Ascend the output file out of the 'data' chunk -- this will cause // the chunk size of the 'data' chunk to be written. if( 0 != mmioAscend( hmmioOut, pckOut, 0 ) ) return E_FAIL; // Do this here instead... if( 0 != mmioAscend( hmmioOut, pckOutRIFF, 0 ) ) return E_FAIL; mmioSeek( hmmioOut, 0, SEEK_SET ); if( 0 != (INT)mmioDescend( hmmioOut, pckOutRIFF, NULL, 0 ) ) return E_FAIL; pckOut->ckid = mmioFOURCC('f', 'a', 'c', 't'); if( 0 == mmioDescend( hmmioOut, pckOut, pckOutRIFF, MMIO_FINDCHUNK ) ) { mmioWrite( hmmioOut, (HPSTR)&dwSamples, sizeof(DWORD) ); mmioAscend( hmmioOut, pckOut, 0 ); } // Ascend the output file out of the 'RIFF' chunk -- this will cause // the chunk size of the 'RIFF' chunk to be written. if( 0 != mmioAscend( hmmioOut, pckOutRIFF, 0 ) ) return E_FAIL; mmioClose( hmmioOut, 0 ); return S_OK; }
/* reads all non-junk chunks into the extrachunk-structure until it finds * the given chunk or the optional parent-chunk is at the end */ HRESULT FindChunkAndKeepExtras(LPEXTRACHUNKS extra,HMMIO hmmio,MMCKINFO *lpck, MMCKINFO *lpckParent,UINT flags) { FOURCC ckid; FOURCC fccType; HRESULT hr; /* pre-conditions */ assert(extra != NULL); assert(hmmio != NULL); assert(lpck != NULL); TRACE("({%p,%lu},%p,%p,%p,0x%X)\n", extra->lp, extra->cb, hmmio, lpck, lpckParent, flags); /* what chunk id and form/list type should we search? */ if (flags & MMIO_FINDCHUNK) { ckid = lpck->ckid; fccType = 0; } else if (flags & MMIO_FINDLIST) { ckid = FOURCC_LIST; fccType = lpck->fccType; } else if (flags & MMIO_FINDRIFF) { ckid = FOURCC_RIFF; fccType = lpck->fccType; } else ckid = fccType = (FOURCC)-1; /* collect everything into extra! */ TRACE(": find ckid=0x%08lX fccType=0x%08lX\n", ckid, fccType); for (;;) { hr = mmioDescend(hmmio, lpck, lpckParent, 0); if (hr != S_OK) { /* No extra chunks in front of desired chunk? */ if (flags == 0 && hr == MMIOERR_CHUNKNOTFOUND) hr = AVIERR_OK; return hr; } /* Have we found what we search for? */ if ((lpck->ckid == ckid) && (fccType == (FOURCC)0 || lpck->fccType == fccType)) return AVIERR_OK; /* Skip padding chunks, the others put into the extrachunk-structure */ if (lpck->ckid == ckidAVIPADDING || lpck->ckid == mmioFOURCC('p','a','d','d')) hr = mmioAscend(hmmio, lpck, 0); else hr = ReadChunkIntoExtra(extra, hmmio, lpck); if (FAILED(hr)) return hr; } }
DWORD CMmio::DescendChunk (FOURCC chunk) { ASSERT (m_hMmio != NULL); ASSERT_VALID (this); memset (&m_mckiChunk, 0, sizeof (MMCKINFO)); m_mckiChunk.ckid = chunk; if (mmioDescend (m_hMmio, &m_mckiChunk, &m_mckiList[m_iListDepth-1], MMIO_FINDCHUNK) != 0) { ThrowError (ERR_MMIO_DESCEND_CHUNK); } return (m_mckiChunk.cksize); }
SoundBuffer::SoundBuffer(std::string filePath) { HMMIO hMmio = NULL; MMIOINFO mmioInfo = {}; hMmio = mmioOpen(const_cast<LPSTR>(filePath.c_str()), &mmioInfo, MMIO_READ); if (!hMmio) throw std::runtime_error("Failed open " + filePath); MMRESULT mmResult; MMCKINFO riffChunk; riffChunk.fccType = mmioFOURCC('W', 'A', 'V', 'E'); mmResult = mmioDescend(hMmio, &riffChunk, NULL, MMIO_FINDRIFF); //TODO:error check MMCKINFO formatChunk; formatChunk.ckid = mmioFOURCC('f', 'm', 't', ' '); mmResult = mmioDescend(hMmio, &formatChunk, &riffChunk, MMIO_FINDCHUNK); //TODO:error check mmioRead(hMmio, (HPSTR)&waveFormatEx, formatChunk.cksize); //TODO:error check mmioAscend(hMmio, &formatChunk, 0); MMCKINFO dataChunk; dataChunk.ckid = mmioFOURCC('d', 'a', 't', 'a'); mmResult = mmioDescend(hMmio, &dataChunk, &riffChunk, MMIO_FINDCHUNK); //TODO:error check buffer.resize(dataChunk.cksize); size = mmioRead(hMmio, (HPSTR)buffer.data(), dataChunk.cksize); //TODO:error check mmioClose(hMmio, 0); }
//----------------------------------------------------------------------------- // Name: WaveStartDataRead() // Desc: Routine has to be called before WaveReadFile as it searches for the // chunk to descend into for reading, that is, the 'data' chunk. For // simplicity, this used to be in the open routine, but was taken out and // moved to a separate routine so there was more control on the chunks // that are before the data chunk, such as 'fact', etc... //----------------------------------------------------------------------------- HRESULT WaveStartDataRead( HMMIO* phmmioIn, MMCKINFO* pckIn, MMCKINFO* pckInRIFF ) { // Seek to the data if( -1 == mmioSeek( *phmmioIn, pckInRIFF->dwDataOffset + sizeof(FOURCC), SEEK_SET ) ) return E_FAIL; // Search the input file for for the 'data' chunk. pckIn->ckid = mmioFOURCC('d', 'a', 't', 'a'); if( 0 != mmioDescend( *phmmioIn, pckIn, pckInRIFF, MMIO_FINDCHUNK ) ) return E_FAIL; return S_OK; }
void CWaveFile::CloseFile() { // Close the file // mmioinfoOut.dwFlags |= MMIO_DIRTY; mmioSetInfo(hmmioOut, &mmioinfoOut, 0); mmioAscend(hmmioOut, &ckOut, 0); mmioAscend(hmmioOut, &ckOutRIFF, 0); mmioSeek(hmmioOut, 0, SEEK_SET); mmioDescend(hmmioOut, &ckOutRIFF, NULL, 0); mmioClose(hmmioOut, 0); }
DWORD CMmio::DescendRiff (FOURCC chunk) { ASSERT (m_hMmio != NULL); ASSERT_VALID (this); memset (&m_mckiRiff, 0, sizeof (m_mckiRiff)); m_mckiRiff.ckid = mmioFOURCC ('R', 'I', 'F', 'F'); m_mckiRiff.fccType = chunk; if (mmioDescend (m_hMmio, &m_mckiRiff, NULL, MMIO_FINDRIFF) != 0) { ThrowError (ERR_MMIO_DESCEND_RIFF); } return (m_mckiRiff.cksize); }
//----------------------------------------------------------------------------- // Name: CHMWaveFile::ResetFile() // Desc: Resets the internal m_ck pointer so reading starts from the // beginning of the file again //----------------------------------------------------------------------------- HRESULT CHMWaveFile::ResetFile() { if( m_bIsReadingFromMemory ) { m_pbDataCur = m_pbData; } else { if( m_hmmio == NULL ) return CO_E_NOTINITIALIZED; if( m_dwFlags == WAVEFILE_READ ) { // Seek to the data if( -1 == mmioSeek( m_hmmio, m_ckRiff.dwDataOffset + sizeof(FOURCC), SEEK_SET ) ) //return DXTRACE_ERR( TEXT("mmioSeek"), E_FAIL ); return -1; // 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 ) ) //return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); return -1; } 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 ) ) //return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL ); return -1; if( 0 != mmioGetInfo( m_hmmio, &m_mmioinfoOut, 0 ) ) //return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL ); return -1; } } return S_OK; }
int WaveStartDataRead( HMMIO *phmmioIn, MMCKINFO *pckIn, MMCKINFO *pckInRIFF ) { int nError=0; // Perform a seek... if ((nError = mmioSeek(*phmmioIn, pckInRIFF->dwDataOffset + sizeof(FOURCC), SEEK_SET)) == -1) { // ASSERT(FALSE); } nError = 0; // Search the input file for for the 'data' chunk. pckIn->ckid = mmioFOURCC('d', 'a', 't', 'a'); nError = mmioDescend(*phmmioIn, pckIn, pckInRIFF, MMIO_FINDCHUNK); return(nError); }
/************************************************************************** * mmioDescend [MMSYSTEM.1223] */ MMRESULT16 WINAPI mmioDescend16(HMMIO16 hmmio, LPMMCKINFO lpck, const MMCKINFO* lpckParent, UINT16 uFlags) { return mmioDescend(HMMIO_32(hmmio), lpck, lpckParent, uFlags); }
int load_wave_file(const char* fname, LPWAVEHDR hdr, LPWAVEFORMATEX format) { HMMIO hmmio; /* file handle for open file */ MMCKINFO mmckinfoParent; /* parent chunk information structure */ MMCKINFO mmckinfoSubchunk; /* subchunk information structure */ DWORD dwFmtSize; /* size of "fmt" chunk */ DWORD dwDataSize; /* size of "data" chunk */ /* * Open the given file for reading with buffered I/O * using the default internal buffer. */ hmmio = mmioOpen((LPSTR) fname, NULL, MMIO_READ | MMIO_ALLOCBUF); if (hmmio == NULL) { Print("load_wave_file(): '%s' - Failed to open file.\n", fname); return 0; } /* * Locate a "RIFF" chunk with a "WAVE" form type * to make sure the file is a WAVE file. */ mmckinfoParent.fccType = mmioFOURCC('W', 'A', 'V', 'E'); if (mmioDescend(hmmio, (LPMMCKINFO) &mmckinfoParent, NULL, MMIO_FINDRIFF)) { Print("load_wave_file(): '%s' - This is not a WAVE file.\n", fname); mmioClose(hmmio, 0); return 0; } /* * Find the "fmt " chunk (form type "fmt "); it must be * a subchunk of the "RIFF" parent chunk. */ mmckinfoSubchunk.ckid = mmioFOURCC('f', 'm', 't', ' '); if (mmioDescend(hmmio, &mmckinfoSubchunk, &mmckinfoParent, MMIO_FINDCHUNK)) { Print("load_wave_file(): '%s' - WAVE file has no \"fmt\" chunk\n", fname); mmioClose(hmmio, 0); return 0; } /* * Get the size of the "fmt " chunk--allocate and lock memory for it. */ dwFmtSize = mmckinfoSubchunk.cksize; /* Read the "fmt " chunk. */ if (mmioRead(hmmio, (HPSTR) format, dwFmtSize) != (LRESULT)dwFmtSize) { Print("load_wave_file(): '%s' - Failed to read format chunk.\n", fname); mmioClose(hmmio, 0); return 0; } /* Ascend out of the "fmt " subchunk. */ mmioAscend(hmmio, &mmckinfoSubchunk, 0); /* * Find the data subchunk. The current file position * should be at the beginning of the data chunk. */ mmckinfoSubchunk.ckid = mmioFOURCC('d', 'a', 't', 'a'); if (mmioDescend(hmmio, &mmckinfoSubchunk, &mmckinfoParent, MMIO_FINDCHUNK)) { Print("load_wave_file(): '%s' - WAVE file has no data chunk.\n", fname); mmioClose(hmmio, 0); return 0; } /* Get the size of the data subchunk. */ dwDataSize = mmckinfoSubchunk.cksize; if (dwDataSize == 0L) { Print("load_wave_file(): '%s' - The data chunk contains no data.\n", fname); mmioClose(hmmio, 0); return 0; } // allocate the data block: hdr->lpData = (LPSTR) new(__FILE__,__LINE__) BYTE[dwDataSize]; hdr->dwBufferLength = dwDataSize; /* Read the waveform data subchunk. */ if (mmioRead(hmmio, (HPSTR) hdr->lpData, dwDataSize) != (LRESULT)dwDataSize) { Print("load_wave_file(): '%s' - Failed to read data chunk.\n", fname); mmioClose(hmmio, 0); return 0; } /* Close the file. */ mmioClose(hmmio, 0); return 1; }
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; } }
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); }
//WAVEファイルをロードする int WaveLoader::ReadWaveData(WAVEFORMATEX* wfx, void** pdata, QWORD dwFrom, QWORD dwSizeToRead, bool isLoopWave) { static MMCKINFO parent, child; static char szBefore[MAX_PATH]; _ASSERT(m_FileInfo->name); if(pdata!=NULL) SAFE_GLOBALFREE(*pdata); //if(m_hmmio!=NULL && lstrcmp(m_FileInfo->name, szBefore)!=0){//ファイル名が指定されていたら開きなおす // SAFE_MMIOCLOSE(m_hmmio); //} if( !isLoaded ){ lstrcpy(szBefore, m_FileInfo->name); if( lstrcmp(m_FileInfo->name, CSL_LOAD_MEMORYIMAGE)==0 ){ // if(!m_hmmio){//最初の一回しかしない処理(ストリーミング用の処置) MMIOINFO mmioinfo; zeroMem(&mmioinfo, sizeof(MMIOINFO)); mmioinfo.pchBuffer = (HPSTR)m_FileInfo->pMemBuffer; mmioinfo.fccIOProc = FOURCC_MEM; mmioinfo.cchBuffer = m_FileInfo->fsize; if(NULL == (m_hmmio = mmioOpen(NULL, &mmioinfo, MMIO_READ|MMIO_ALLOCBUF))){ return CSL_E_UNEXP; } }else{ if(NULL == (m_hmmio = mmioOpen((LPSTR)m_FileInfo->name, NULL, MMIO_READ|MMIO_ALLOCBUF))){ return CSL_E_UNEXP; } } parent.fccType = mmioFOURCC('W', 'A', 'V', 'E');//waveファイルかどうか調べる if(mmioDescend(m_hmmio, &parent, NULL, MMIO_FINDRIFF) != MMSYSERR_NOERROR){ SAFE_MMIOCLOSE(m_hmmio); return CSL_E_UNEXP; } child.ckid = mmioFOURCC('f', 'm', 't', ' ');//fmtチャンクへ移動する if(mmioDescend(m_hmmio, &child, &parent, MMIO_FINDCHUNK) != MMSYSERR_NOERROR){ SAFE_MMIOCLOSE(m_hmmio); return CSL_E_UNEXP; } _ASSERT(wfx); if(mmioRead(m_hmmio, (HPSTR)wfx, (LONG)child.cksize) != (LONG)child.cksize){//fmtチャンク(WAVEFORMATEX)読み取り SAFE_MMIOCLOSE(m_hmmio); return CSL_E_UNEXP; } _ASSERT((wfx->wFormatTag==WAVE_FORMAT_PCM)); mmioAscend(m_hmmio, &child, 0);//fmtチャンクから出る child.ckid = mmioFOURCC('d', 'a', 't', 'a');//dataチャンクに移動 if(mmioDescend(m_hmmio, &child, &parent, MMIO_FINDCHUNK) != MMSYSERR_NOERROR) { SAFE_MMIOCLOSE(m_hmmio); return CSL_E_UNEXP; } m_dwDataLength = child.cksize;//WAVE領域のサイズ m_dwOffsetToWaveData = mmioSeek(m_hmmio, 0, SEEK_CUR);//データまでの位置を保存しておく } if(pdata){ if(dwSizeToRead<=0){//ファイル全体を読み込む (*pdata) = (LPBYTE)GlobalAlloc(GPTR, m_dwDataLength * sizeof(BYTE)); _ASSERT(*pdata); if(mmioRead(m_hmmio, (HPSTR)*pdata, (LONG)m_dwDataLength) != (LONG)m_dwDataLength){ GlobalFree(*pdata); SAFE_MMIOCLOSE(m_hmmio); return CSL_E_UNEXP; } SAFE_MMIOCLOSE(m_hmmio); //必要なデータがそろったので、ファイルを閉じる m_dwCurrentDecodedPos += dwSizeToRead; }else{ //DWORD dwInnerFinPos = dwFrom + dwSizeToRead; ////領域サイズ以上だったら収まるように値を補正 //if(m_dwDataLength < dwInnerFinPos){ // dwSizeToRead -= dwInnerFinPos-m_dwDataLength; //} //開始位置が指定されていれば, データ領域からのオフセットをStartとする. //指定されていなければ, それまで進んだカーソル位置から読み込みを開始する if(dwFrom>=0) mmioSeek(m_hmmio, (LONG)(m_dwOffsetToWaveData + dwFrom), SEEK_SET); //要求領域分のメモリ確保 (*pdata) = (LPBYTE)GlobalAlloc(GPTR, (SIZE_T)(dwSizeToRead * sizeof(BYTE))); _ASSERT(*pdata); //現在位置からリクエストサイズを読むとオーバーするようなら、ラップアラウンドする。 DWORD dwNowCursor = mmioSeek(m_hmmio, 0, SEEK_CUR) - m_dwOffsetToWaveData; if(m_dwDataLength < (dwNowCursor + dwSizeToRead)){ if( !isLoopWave ){ if( dwNowCursor>=m_dwDataLength ){ fillMem((BYTE*)*pdata, dwSizeToRead, (m_wfx.wBitsPerSample==8) ? 128:0); return CSL_E_OUTOFRANGE; } } DWORD dwBeforeWrapAround = m_dwDataLength-dwNowCursor; //とりあえず、最後まで読む if(mmioRead(m_hmmio, (HPSTR)*pdata, (LONG)dwBeforeWrapAround) != (LONG)dwBeforeWrapAround){ GlobalFree(*pdata); SAFE_MMIOCLOSE(m_hmmio); return CSL_E_UNEXP; } m_dwCurrentDecodedPos += dwBeforeWrapAround; if(isLoopWave){//残った部分を無音で埋めるかどうか mmioSeek(m_hmmio, 0, SEEK_SET); mmioSeek(m_hmmio, m_dwOffsetToWaveData, SEEK_CUR); //ポインタをWAVE領域始点に戻す //ラップアラウンド分を読む if(mmioRead(m_hmmio, (HPSTR)*pdata+dwBeforeWrapAround, (LONG)(dwSizeToRead - dwBeforeWrapAround)) != (LONG)(dwSizeToRead - dwBeforeWrapAround)){ GlobalFree(*pdata); SAFE_MMIOCLOSE(m_hmmio); return CSL_E_UNEXP; } m_dwCurrentDecodedPos = 0; m_dwCurrentDecodedPos += dwSizeToRead - dwBeforeWrapAround; }else{ fillMem((BYTE*)*pdata+dwBeforeWrapAround, dwSizeToRead - dwBeforeWrapAround, (m_wfx.wBitsPerSample==8) ? 128:0); return CSL_N_FIN; } }else{ //ラップアラウンドしなかった場合 if(mmioRead(m_hmmio, (HPSTR)*pdata, (LONG)dwSizeToRead) != (LONG)dwSizeToRead){ GlobalFree(*pdata); SAFE_MMIOCLOSE(m_hmmio); return CSL_E_UNEXP; } m_dwCurrentDecodedPos += dwSizeToRead; }//必要なデータはまだあるので、ファイルは閉じない } } return CSL_E_OK; }
int WaveCopyUselessChunks( HMMIO *phmmioIn, MMCKINFO *pckIn, MMCKINFO *pckInRiff, HMMIO *phmmioOut, MMCKINFO *pckOut, MMCKINFO *pckOutRiff) { int nError; nError = 0; // First seek to the stinking start of the file, not including the riff header... if ((nError = mmioSeek(*phmmioIn, pckInRiff->dwDataOffset + sizeof(FOURCC), SEEK_SET)) == -1) { nError = ER_CANNOTREAD; goto ERROR_IN_PROC; } nError = 0; while (mmioDescend(*phmmioIn, pckIn, pckInRiff, 0) == 0) { // quickly check for corrupt RIFF file--don't ascend past end! if ((pckIn->dwDataOffset + pckIn->cksize) > (pckInRiff->dwDataOffset + pckInRiff->cksize)) goto ERROR_IN_PROC; switch (pckIn->ckid) { // explicitly skip these... case mmioFOURCC('f', 'm', 't', ' '): break; case mmioFOURCC('d', 'a', 't', 'a'): break; case mmioFOURCC('f', 'a', 'c', 't'): break; case mmioFOURCC('J', 'U', 'N', 'K'): break; case mmioFOURCC('P', 'A', 'D', ' '): break; case mmioFOURCC('c', 'u', 'e', ' '): break; // copy chunks that are OK to copy case mmioFOURCC('p', 'l', 's', 't'): // although without the 'cue' chunk, it doesn't make much sense riffCopyChunk(*phmmioIn, *phmmioOut, pckIn); break; case mmioFOURCC('D', 'I', 'S', 'P'): riffCopyChunk(*phmmioIn, *phmmioOut, pckIn); break; // don't copy unknown chunks default: break; } // step up to prepare for next chunk.. mmioAscend(*phmmioIn, pckIn, 0); } ERROR_IN_PROC: { int nErrorT; // Seek back to riff header nErrorT = mmioSeek(*phmmioIn, pckInRiff->dwDataOffset + sizeof(FOURCC), SEEK_SET); } return(nError); }
int WaveCloseWriteFile( HMMIO *phmmioOut, // (IN) MMCKINFO *pckOut, // (IN) MMCKINFO *pckOutRIFF, // (IN) MMIOINFO *pmmioinfoOut, // (IN) DWORD cSamples // (IN) ) { int nError; nError = 0; if (*phmmioOut == NULL) return(0); pmmioinfoOut->dwFlags |= MMIO_DIRTY; if ((nError = mmioSetInfo(*phmmioOut, pmmioinfoOut, 0)) != 0) { // cannot flush, probably... goto ERROR_CANNOT_WRITE; } /* Ascend the output file out of the 'data' chunk -- this will cause * the chunk size of the 'data' chunk to be written. */ if ((nError = mmioAscend(*phmmioOut, pckOut, 0)) != 0) goto ERROR_CANNOT_WRITE; // cannot write file, probably // Do this here instead... if ((nError = mmioAscend(*phmmioOut, pckOutRIFF, 0)) != 0) goto ERROR_CANNOT_WRITE; // cannot write file, probably nError = mmioSeek(*phmmioOut, 0, SEEK_SET); if ((nError = (int)mmioDescend(*phmmioOut, pckOutRIFF, NULL, 0)) != 0) goto ERROR_CANNOT_WRITE; nError = 0; pckOut->ckid = mmioFOURCC('f', 'a', 'c', 't'); if ((nError = mmioDescend(*phmmioOut, pckOut, pckOutRIFF, MMIO_FINDCHUNK)) == 0) { // If it didn't fail, write the fact chunk out, if it failed, not critical, just // assert (below). nError = mmioWrite(*phmmioOut, (HPSTR)&cSamples, sizeof(DWORD)); nError = mmioAscend(*phmmioOut, pckOut, 0); nError = 0; } else { nError = 0; // ASSERT(FALSE); } /* Ascend the output file out of the 'RIFF' chunk -- this will cause * the chunk size of the 'RIFF' chunk to be written. */ if ((nError = mmioAscend(*phmmioOut, pckOutRIFF, 0)) != 0) goto ERROR_CANNOT_WRITE; // cannot write file, probably ERROR_CANNOT_WRITE: if (*phmmioOut != NULL) { mmioClose(*phmmioOut, 0); *phmmioOut = NULL; } return(nError); }
bool CSoundFile::OpenWaveFile() { // code taken from Visual C++ Multimedia -- Aitken and Jarol p 122 // check if file is already open if(m_hFile) return FALSE; m_hFile = mmioOpen(m_szFileName,NULL,MMIO_READ); if(m_hFile == NULL) { m_Mode = FILE_ERROR; return FALSE; } m_MMCKInfoParent.fccType = mmioFOURCC('W','A','V','E'); MMRESULT mmResult = ::mmioDescend(m_hFile, &m_MMCKInfoParent,NULL,MMIO_FINDRIFF); if(mmResult) { //CString tstr; //tstr.LoadString(IDS_STRING_ERRDESCENT); //AfxMessageBox(tstr); AfxMessageBox("Error descending into file"); mmioClose(m_hFile,0); m_hFile = NULL; m_Mode = FILE_ERROR; return FALSE; } m_MMCKInfoChild.ckid = mmioFOURCC('f','m','t',' '); mmResult = mmioDescend(m_hFile,&m_MMCKInfoChild,&m_MMCKInfoParent,MMIO_FINDCHUNK); if(mmResult) { AfxMessageBox("Error descending in wave file"); mmioClose(m_hFile,0); m_Mode = FILE_ERROR; m_hFile = NULL; return FALSE; } DWORD bytesRead = mmioRead(m_hFile,(LPSTR)&m_Format,m_MMCKInfoChild.cksize); if(bytesRead < 0) { AfxMessageBox("Error reading PCM wave format record"); mmioClose(m_hFile,0); m_Mode = FILE_ERROR; return FALSE; } // open output sound file mmResult = mmioAscend(m_hFile,&m_MMCKInfoChild,0); if(mmResult) { AfxMessageBox("Error ascending in File"); mmioClose(m_hFile,0); m_hFile = NULL; m_Mode = FILE_ERROR; return FALSE; } m_MMCKInfoChild.ckid = mmioFOURCC('d','a','t','a'); mmResult = mmioDescend(m_hFile,&m_MMCKInfoChild, &m_MMCKInfoParent,MMIO_FINDCHUNK); if(mmResult) { AfxMessageBox("error reading data chunk"); mmioClose(m_hFile,0); m_hFile = NULL; m_Mode = FILE_ERROR; return FALSE; } return TRUE; }
static BOOL ANIMATE_GetAviInfo(ANIMATE_INFO *infoPtr) { MMCKINFO ckMainRIFF; MMCKINFO mmckHead; MMCKINFO mmckList; MMCKINFO mmckInfo; DWORD numFrame; DWORD insize; if (mmioDescend(infoPtr->hMMio, &ckMainRIFF, NULL, 0) != 0) { WARN("Can't find 'RIFF' chunk\n"); return FALSE; } if ((ckMainRIFF.ckid != FOURCC_RIFF) || (ckMainRIFF.fccType != mmioFOURCC('A', 'V', 'I', ' '))) { WARN("Can't find 'AVI ' chunk\n"); return FALSE; } mmckHead.fccType = mmioFOURCC('h', 'd', 'r', 'l'); if (mmioDescend(infoPtr->hMMio, &mmckHead, &ckMainRIFF, MMIO_FINDLIST) != 0) { WARN("Can't find 'hdrl' list\n"); return FALSE; } mmckInfo.ckid = mmioFOURCC('a', 'v', 'i', 'h'); if (mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckHead, MMIO_FINDCHUNK) != 0) { WARN("Can't find 'avih' chunk\n"); return FALSE; } mmioRead(infoPtr->hMMio, (LPSTR)&infoPtr->mah, sizeof(infoPtr->mah)); TRACE("mah.dwMicroSecPerFrame=%d\n", infoPtr->mah.dwMicroSecPerFrame); TRACE("mah.dwMaxBytesPerSec=%d\n", infoPtr->mah.dwMaxBytesPerSec); TRACE("mah.dwPaddingGranularity=%d\n", infoPtr->mah.dwPaddingGranularity); TRACE("mah.dwFlags=%d\n", infoPtr->mah.dwFlags); TRACE("mah.dwTotalFrames=%d\n", infoPtr->mah.dwTotalFrames); TRACE("mah.dwInitialFrames=%d\n", infoPtr->mah.dwInitialFrames); TRACE("mah.dwStreams=%d\n", infoPtr->mah.dwStreams); TRACE("mah.dwSuggestedBufferSize=%d\n", infoPtr->mah.dwSuggestedBufferSize); TRACE("mah.dwWidth=%d\n", infoPtr->mah.dwWidth); TRACE("mah.dwHeight=%d\n", infoPtr->mah.dwHeight); mmioAscend(infoPtr->hMMio, &mmckInfo, 0); mmckList.fccType = mmioFOURCC('s', 't', 'r', 'l'); if (mmioDescend(infoPtr->hMMio, &mmckList, &mmckHead, MMIO_FINDLIST) != 0) { WARN("Can't find 'strl' list\n"); return FALSE; } mmckInfo.ckid = mmioFOURCC('s', 't', 'r', 'h'); if (mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckList, MMIO_FINDCHUNK) != 0) { WARN("Can't find 'strh' chunk\n"); return FALSE; } mmioRead(infoPtr->hMMio, (LPSTR)&infoPtr->ash, sizeof(infoPtr->ash)); TRACE("ash.fccType='%c%c%c%c'\n", LOBYTE(LOWORD(infoPtr->ash.fccType)), HIBYTE(LOWORD(infoPtr->ash.fccType)), LOBYTE(HIWORD(infoPtr->ash.fccType)), HIBYTE(HIWORD(infoPtr->ash.fccType))); TRACE("ash.fccHandler='%c%c%c%c'\n", LOBYTE(LOWORD(infoPtr->ash.fccHandler)), HIBYTE(LOWORD(infoPtr->ash.fccHandler)), LOBYTE(HIWORD(infoPtr->ash.fccHandler)), HIBYTE(HIWORD(infoPtr->ash.fccHandler))); TRACE("ash.dwFlags=%d\n", infoPtr->ash.dwFlags); TRACE("ash.wPriority=%d\n", infoPtr->ash.wPriority); TRACE("ash.wLanguage=%d\n", infoPtr->ash.wLanguage); TRACE("ash.dwInitialFrames=%d\n", infoPtr->ash.dwInitialFrames); TRACE("ash.dwScale=%d\n", infoPtr->ash.dwScale); TRACE("ash.dwRate=%d\n", infoPtr->ash.dwRate); TRACE("ash.dwStart=%d\n", infoPtr->ash.dwStart); TRACE("ash.dwLength=%d\n", infoPtr->ash.dwLength); TRACE("ash.dwSuggestedBufferSize=%d\n", infoPtr->ash.dwSuggestedBufferSize); TRACE("ash.dwQuality=%d\n", infoPtr->ash.dwQuality); TRACE("ash.dwSampleSize=%d\n", infoPtr->ash.dwSampleSize); TRACE("ash.rcFrame=(%d,%d,%d,%d)\n", infoPtr->ash.rcFrame.top, infoPtr->ash.rcFrame.left, infoPtr->ash.rcFrame.bottom, infoPtr->ash.rcFrame.right); mmioAscend(infoPtr->hMMio, &mmckInfo, 0); mmckInfo.ckid = mmioFOURCC('s', 't', 'r', 'f'); if (mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckList, MMIO_FINDCHUNK) != 0) { WARN("Can't find 'strh' chunk\n"); return FALSE; } infoPtr->inbih = Alloc(mmckInfo.cksize); if (!infoPtr->inbih) { WARN("Can't alloc input BIH\n"); return FALSE; } mmioRead(infoPtr->hMMio, (LPSTR)infoPtr->inbih, mmckInfo.cksize); TRACE("bih.biSize=%d\n", infoPtr->inbih->biSize); TRACE("bih.biWidth=%d\n", infoPtr->inbih->biWidth); TRACE("bih.biHeight=%d\n", infoPtr->inbih->biHeight); TRACE("bih.biPlanes=%d\n", infoPtr->inbih->biPlanes); TRACE("bih.biBitCount=%d\n", infoPtr->inbih->biBitCount); TRACE("bih.biCompression=%d\n", infoPtr->inbih->biCompression); TRACE("bih.biSizeImage=%d\n", infoPtr->inbih->biSizeImage); TRACE("bih.biXPelsPerMeter=%d\n", infoPtr->inbih->biXPelsPerMeter); TRACE("bih.biYPelsPerMeter=%d\n", infoPtr->inbih->biYPelsPerMeter); TRACE("bih.biClrUsed=%d\n", infoPtr->inbih->biClrUsed); TRACE("bih.biClrImportant=%d\n", infoPtr->inbih->biClrImportant); mmioAscend(infoPtr->hMMio, &mmckInfo, 0); mmioAscend(infoPtr->hMMio, &mmckList, 0); #if 0 /* an AVI has 0 or 1 video stream, and to be animated should not contain * an audio stream, so only one strl is allowed */ mmckList.fccType = mmioFOURCC('s', 't', 'r', 'l'); if (mmioDescend(infoPtr->hMMio, &mmckList, &mmckHead, MMIO_FINDLIST) == 0) { WARN("There should be a single 'strl' list\n"); return FALSE; } #endif mmioAscend(infoPtr->hMMio, &mmckHead, 0); /* no need to read optional JUNK chunk */ mmckList.fccType = mmioFOURCC('m', 'o', 'v', 'i'); if (mmioDescend(infoPtr->hMMio, &mmckList, &ckMainRIFF, MMIO_FINDLIST) != 0) { WARN("Can't find 'movi' list\n"); return FALSE; } /* FIXME: should handle the 'rec ' LIST when present */ infoPtr->lpIndex = Alloc(infoPtr->mah.dwTotalFrames * sizeof(DWORD)); if (!infoPtr->lpIndex) return FALSE; numFrame = insize = 0; while (mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckList, 0) == 0 && numFrame < infoPtr->mah.dwTotalFrames) { infoPtr->lpIndex[numFrame] = mmckInfo.dwDataOffset; if (insize < mmckInfo.cksize) insize = mmckInfo.cksize; numFrame++; mmioAscend(infoPtr->hMMio, &mmckInfo, 0); } if (numFrame != infoPtr->mah.dwTotalFrames) { WARN("Found %d frames (/%d)\n", numFrame, infoPtr->mah.dwTotalFrames); return FALSE; } if (insize > infoPtr->ash.dwSuggestedBufferSize) { WARN("insize=%d suggestedSize=%d\n", insize, infoPtr->ash.dwSuggestedBufferSize); infoPtr->ash.dwSuggestedBufferSize = insize; } infoPtr->indata = Alloc(infoPtr->ash.dwSuggestedBufferSize); if (!infoPtr->indata) return FALSE; return TRUE; }
/* This function will open a wave input file and prepare it for reading, * so the data can be easily * read with WaveReadFile. Returns 0 if successful, the error code if not. * pszFileName - Input filename to load. * phmmioIn - Pointer to handle which will be used * for further mmio routines. * ppwfxInfo - Ptr to ptr to WaveFormatEx structure * with all info about the file. * */ int WaveOpenFile( TCHAR*pszFileName, // (IN) HMMIO *phmmioIn, // (OUT) WAVEFORMATEX **ppwfxInfo, // (OUT) MMCKINFO *pckInRIFF // (OUT) ) { HMMIO hmmioIn; MMCKINFO ckIn; // chunk info. for general use. PCMWAVEFORMAT pcmWaveFormat; // Temp PCM structure to load in. WORD cbExtraAlloc; // Extra bytes for waveformatex int nError; // Return value. // Initialization... *ppwfxInfo = NULL; nError = 0; hmmioIn = NULL; if ((hmmioIn = mmioOpen(pszFileName, NULL, MMIO_ALLOCBUF | MMIO_READ)) == NULL) { nError = ER_CANNOTOPEN; goto ERROR_READING_WAVE; } if ((nError = (int)mmioDescend(hmmioIn, pckInRIFF, NULL, 0)) != 0) { goto ERROR_READING_WAVE; } if ((pckInRIFF->ckid != FOURCC_RIFF) || (pckInRIFF->fccType != mmioFOURCC('W', 'A', 'V', 'E'))) { nError = ER_NOTWAVEFILE; goto ERROR_READING_WAVE; } /* Search the input file for for the 'fmt ' chunk. */ ckIn.ckid = mmioFOURCC('f', 'm', 't', ' '); if ((nError = (int)mmioDescend(hmmioIn, &ckIn, pckInRIFF, MMIO_FINDCHUNK)) != 0) { goto ERROR_READING_WAVE; } /* 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)) { nError = ER_NOTWAVEFILE; goto ERROR_READING_WAVE; } /* Read the 'fmt ' chunk into <pcmWaveFormat>.*/ if (mmioRead(hmmioIn, (HPSTR) &pcmWaveFormat, (long) sizeof(pcmWaveFormat)) != (long) sizeof(pcmWaveFormat)) { nError = ER_CANNOTREAD; goto ERROR_READING_WAVE; } // Ok, 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) cbExtraAlloc = 0; else { // Read in length of extra bytes. if (mmioRead(hmmioIn, (LPTSTR) &cbExtraAlloc, (long) sizeof(cbExtraAlloc)) != (long) sizeof(cbExtraAlloc)) { nError = ER_CANNOTREAD; goto ERROR_READING_WAVE; } } // Ok, now allocate that waveformatex structure. if ((*ppwfxInfo = GlobalAlloc(GMEM_FIXED, sizeof(WAVEFORMATEX)+cbExtraAlloc)) == NULL) { nError = ER_MEM; goto ERROR_READING_WAVE; } // Copy the bytes from the pcm structure to the waveformatex structure memcpy(*ppwfxInfo, &pcmWaveFormat, sizeof(pcmWaveFormat)); (*ppwfxInfo)->cbSize = cbExtraAlloc; // Now, read those extra bytes into the structure, if cbExtraAlloc != 0. if (cbExtraAlloc != 0) { if (mmioRead(hmmioIn, (LPTSTR) (((BYTE*)&((*ppwfxInfo)->cbSize))+sizeof(cbExtraAlloc)), (long) (cbExtraAlloc)) != (long) (cbExtraAlloc)) { nError = ER_NOTWAVEFILE; goto ERROR_READING_WAVE; } } /* Ascend the input file out of the 'fmt ' chunk. */ if ((nError = mmioAscend(hmmioIn, &ckIn, 0)) != 0) { goto ERROR_READING_WAVE; } goto TEMPCLEANUP; ERROR_READING_WAVE: if (*ppwfxInfo != NULL) { GlobalFree(*ppwfxInfo); *ppwfxInfo = NULL; } if (hmmioIn != NULL) { mmioClose(hmmioIn, 0); hmmioIn = NULL; } TEMPCLEANUP: *phmmioIn = hmmioIn; return(nError); }
void CSoundMgr::Play (int iChannel, int iVolume, int iPan) // Play // // Plays a channel. // // iVolume = 0 for maximum volume. // iVolume = -10,000 for minimum volume. { if (m_pDS == NULL || m_iSoundVolume == 0) return; SChannel *pChannel = GetChannel(iChannel); if (pChannel->pBuffer == NULL) return; // If the buffer is lost, then we need to restore it DWORD dwStatus; pChannel->pBuffer->GetStatus(&dwStatus); if (dwStatus & DSBSTATUS_BUFFERLOST) { if (FAILED(pChannel->pBuffer->Restore())) return; if (pChannel->sFilename.IsBlank()) return; // Open the file MMCKINFO parent, child; ::ZeroMemory(&parent, sizeof(parent)); ::ZeroMemory(&child, sizeof(child)); HMMIO hFile = mmioOpen(pChannel->sFilename.GetASCIIZPointer(), NULL, MMIO_READ | MMIO_ALLOCBUF); if (hFile == NULL) return; // Descend into the RIFF parent.fccType = mmioFOURCC('W', 'A', 'V', 'E'); if (mmioDescend(hFile, &parent, NULL, MMIO_FINDRIFF)) { mmioClose(hFile, 0); return; } child.ckid = mmioFOURCC('d', 'a', 't', 'a'); if (mmioDescend(hFile, &child, &parent, MMIO_FINDCHUNK)) { mmioClose(hFile, 0); return; } DWORD dwDataSize = child.cksize; // Now read into the buffer LPVOID pDest; DWORD dwDestSize; if (FAILED(pChannel->pBuffer->Lock(0, 0, &pDest, &dwDestSize, NULL, NULL, DSBLOCK_ENTIREBUFFER))) { mmioClose(hFile, 0); return; } if (mmioRead(hFile, (char *)pDest, dwDestSize) != (LONG)dwDataSize) { mmioClose(hFile, 0); return; } // Done with the wave file mmioClose(hFile, 0); } // Check to see if the channel is busy. If it is, then we may need to create // a second buffer. else if (dwStatus & DSBSTATUS_PLAYING) { SChannel *pLastChannel = pChannel; pChannel = pChannel->pNext; while (pChannel) { pChannel->pBuffer->GetStatus(&dwStatus); if (!(dwStatus & DSBSTATUS_BUFFERLOST) && !(dwStatus & DSBSTATUS_PLAYING)) break; pLastChannel = pChannel; pChannel = pChannel->pNext; } // If we couldn't find another channel, then duplicate the original if (pChannel == NULL) { pChannel = GetChannel(iChannel); LPDIRECTSOUNDBUFFER pNewBuffer = NULL; if (FAILED(m_pDS->DuplicateSoundBuffer(pChannel->pBuffer, &pNewBuffer))) return; SChannel *pNewChannel = new SChannel; pLastChannel->pNext = pNewChannel; pNewChannel->pBuffer = pNewBuffer; pNewChannel->pNext = NULL; pChannel = pNewChannel; } } // Adjust volume int iVolumeAdj = MAX_VOLUME_LEVEL - m_iSoundVolume; int iMaxVolume = -(iVolumeAdj * VOLUME_STEP); int iVolumeRange = iMaxVolume - MIN_VOLUME; iVolume = iMaxVolume - ((iVolumeRange * iVolume) / MIN_VOLUME); // pChannel now points to a valid buffer. Play it! pChannel->pBuffer->SetVolume(iVolume); pChannel->pBuffer->SetPan(iPan); pChannel->pBuffer->Play(0, 0, 0); // Clean-up any channels after us that are done playing SChannel *pLastChannel = pChannel; pChannel = pChannel->pNext; while (pChannel) { pChannel->pBuffer->GetStatus(&dwStatus); if (!(dwStatus & DSBSTATUS_PLAYING)) { pChannel->pBuffer->Release(); pLastChannel->pNext = pChannel->pNext; delete pChannel; pChannel = pLastChannel->pNext; } else { pLastChannel = pChannel; pChannel = pChannel->pNext; } } }
static HRESULT AVIFILE_LoadFile(IAVIFileImpl *This) { MMCKINFO ckRIFF; MMCKINFO ck; This->sInfo.dwLength = 0; /* just to be sure */ This->fDirty = FALSE; /* search for RIFF chunk */ ckRIFF.fccType = 0; /* find any */ if (mmioDescend(This->hmmio, &ckRIFF, NULL, MMIO_FINDRIFF) != S_OK) { return AVIFILE_LoadSunFile(This); } if (ckRIFF.fccType != formtypeWAVE) return AVIERR_BADFORMAT; /* search WAVE format chunk */ ck.ckid = ckidWAVEFORMAT; if (FindChunkAndKeepExtras(&This->extra, This->hmmio, &ck, &ckRIFF, MMIO_FINDCHUNK) != S_OK) return AVIERR_FILEREAD; /* get memory for format and read it */ This->lpFormat = HeapAlloc(GetProcessHeap(), 0, ck.cksize); if (This->lpFormat == NULL) return AVIERR_FILEREAD; This->cbFormat = ck.cksize; if (mmioRead(This->hmmio, (HPSTR)This->lpFormat, ck.cksize) != ck.cksize) return AVIERR_FILEREAD; if (mmioAscend(This->hmmio, &ck, 0) != S_OK) return AVIERR_FILEREAD; /* Non-pcm formats have a fact chunk. * We don't need it, so simply add it to the extra chunks. */ /* find the big data chunk */ This->ckData.ckid = ckidWAVEDATA; if (FindChunkAndKeepExtras(&This->extra, This->hmmio, &This->ckData, &ckRIFF, MMIO_FINDCHUNK) != S_OK) return AVIERR_FILEREAD; memset(&This->sInfo, 0, sizeof(This->sInfo)); This->sInfo.fccType = streamtypeAUDIO; This->sInfo.dwRate = This->lpFormat->nAvgBytesPerSec; This->sInfo.dwSampleSize = This->sInfo.dwScale = This->lpFormat->nBlockAlign; This->sInfo.dwLength = This->ckData.cksize / This->lpFormat->nBlockAlign; This->sInfo.dwSuggestedBufferSize = This->ckData.cksize; This->fInfo.dwStreams = 1; if (mmioAscend(This->hmmio, &This->ckData, 0) != S_OK) { /* seems to be truncated */ WARN(": file seems to be truncated!\n"); This->ckData.cksize = mmioSeek(This->hmmio, 0, SEEK_END) - This->ckData.dwDataOffset; This->sInfo.dwLength = This->ckData.cksize / This->lpFormat->nBlockAlign; This->sInfo.dwSuggestedBufferSize = This->ckData.cksize; } /* ignore errors */ FindChunkAndKeepExtras(&This->extra, This->hmmio, &ck, &ckRIFF, 0); return AVIERR_OK; }
//----------------------------------------------------------------------------- // Name: CWaveFile::ReadMMIO() // Desc: Support function for reading from a multimedia I/O stream. // m_hmmio must be valid before calling. This function uses it to // update m_ckRiff, and m_pwfx. //----------------------------------------------------------------------------- HRESULT CWaveFile::ReadMMIO() { MMCKINFO ckIn; // chunk info. for general use. PCMWAVEFORMAT pcmWaveFormat; // Temp PCM structure to load in. m_pwfx = NULL; if( ( 0 != mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) ) ) return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); // 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 DXTRACE_ERR( TEXT("mmioFOURCC"), E_FAIL ); // 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 ) ) return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL ); // 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) ) return DXTRACE_ERR( TEXT("sizeof(PCMWAVEFORMAT)"), E_FAIL ); // Read the 'fmt ' chunk into <pcmWaveFormat>. if( mmioRead( m_hmmio, (HPSTR) &pcmWaveFormat, sizeof(pcmWaveFormat)) != sizeof(pcmWaveFormat) ) return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); // 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 ) return DXTRACE_ERR( TEXT("m_pwfx"), E_FAIL ); // 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) ) return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) + cbExtraBytes ]; if( NULL == m_pwfx ) return DXTRACE_ERR( TEXT("new"), E_FAIL ); // 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 ); return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL ); } } // Ascend the input file out of the 'fmt ' chunk. if( 0 != mmioAscend( m_hmmio, &ckIn, 0 ) ) { SAFE_DELETE( m_pwfx ); return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL ); } return S_OK; }
ALERROR CSoundMgr::LoadWaveFile (HMMIO hFile, int *retiChannel) // LoadWaveFile // // Creates a sound buffer from an open MMIO file { ASSERT(m_pDS); MMCKINFO parent, child; ::ZeroMemory(&parent, sizeof(parent)); ::ZeroMemory(&child, sizeof(child)); // Descend into the RIFF parent.fccType = mmioFOURCC('W', 'A', 'V', 'E'); if (mmioDescend(hFile, &parent, NULL, MMIO_FINDRIFF)) { mmioClose(hFile, 0); return ERR_FAIL; } // Descend to the wave format child.ckid = mmioFOURCC('f', 'm', 't', ' '); if (mmioDescend(hFile, &child, &parent, 0)) { mmioClose(hFile, 0); return ERR_FAIL; } // Allocate a block large enough to hold the format size DWORD dwFmtSize = child.cksize; DWORD dwAllocSize = max(dwFmtSize, sizeof(WAVEFORMATEX)); WAVEFORMATEX *pFormat = (WAVEFORMATEX *)new char [dwAllocSize]; ::ZeroMemory(pFormat, dwAllocSize); if (mmioRead(hFile, (char *)pFormat, dwFmtSize) != (LONG)dwFmtSize) { delete [] (char *)pFormat; mmioClose(hFile, 0); return ERR_FAIL; } // Now descend to the data if (mmioAscend(hFile, &child, 0)) { delete [] (char *)pFormat; mmioClose(hFile, 0); return ERR_FAIL; } child.ckid = mmioFOURCC('d', 'a', 't', 'a'); if (mmioDescend(hFile, &child, &parent, MMIO_FINDCHUNK)) { delete [] (char *)pFormat; mmioClose(hFile, 0); return ERR_FAIL; } DWORD dwDataSize = child.cksize; // Create the DirectSound buffer DSBUFFERDESC dsbdesc; LPDIRECTSOUNDBUFFER pBuffer; ::ZeroMemory(&dsbdesc, sizeof(dsbdesc)); dsbdesc.dwSize = sizeof(dsbdesc); dsbdesc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPAN; dsbdesc.dwBufferBytes = dwDataSize; dsbdesc.lpwfxFormat = pFormat; if (FAILED(m_pDS->CreateSoundBuffer(&dsbdesc, &pBuffer, NULL))) { // If we can't create the sound buffer, try creating the same buffer // but with no volume or pan controls. dsbdesc.dwFlags = 0; if (FAILED(m_pDS->CreateSoundBuffer(&dsbdesc, &pBuffer, NULL))) { delete [] (char *)pFormat; return ERR_FAIL; } } delete [] (char *)pFormat; // Now read into the buffer LPVOID pDest; DWORD dwDestSize; if (FAILED(pBuffer->Lock(0, 0, &pDest, &dwDestSize, NULL, NULL, DSBLOCK_ENTIREBUFFER))) { pBuffer->Release(); mmioClose(hFile, 0); return ERR_FAIL; } if (mmioRead(hFile, (char *)pDest, dwDestSize) != (LONG)dwDataSize) { pBuffer->Release(); mmioClose(hFile, 0); return ERR_FAIL; } // Done with the wave file mmioClose(hFile, 0); // Add to the channel int iChannel = AllocChannel(); SChannel *pChannel = GetChannel(iChannel); pChannel->pBuffer = pBuffer; pChannel->pNext = NULL; // Done if (retiChannel) *retiChannel = iChannel; return NOERROR; }