예제 #1
0
int main(int argc, char* argv[])
{
//    LPWSTR szFileName;//声音文件名
    MMCKINFO mmckinfoParent;
    MMCKINFO mmckinfoSubChunk;
    DWORD dwFmtSize;
    HMMIO m_hmmio;//音频文件句柄
    DWORD m_WaveLong;
    HPSTR lpData;//音频数据
    HANDLE m_hData=NULL;
    HANDLE m_hFormat;
    WAVEFORMATEX * lpFormat;
    DWORD m_dwDataOffset;
    DWORD m_dwDataSize;
    WAVEHDR pWaveOutHdr;
    WAVEOUTCAPS pwoc;
    HWAVEOUT hWaveOut;
    int SoundOffset=0;
    int SoundLong=0;
    int DevsNum;
    //打开波形文件
    if(!(m_hmmio=mmioOpen(argv[1],NULL,MMIO_READ|MMIO_ALLOCBUF)))
    {
    //File open Error
        printf("Failed to open the file.");//错误处理函数
        return false;
    }
    //检查打开文件是否是声音文件
    mmckinfoParent.fccType =mmioFOURCC('W','A','V','E');
    if(mmioDescend(m_hmmio,(LPMMCKINFO)&mmckinfoParent,NULL,MMIO_FINDRIFF))
    {
        printf("NOT WAVE FILE AND QUIT");
        return 0;
    }
    //寻找 'fmt' 块
    mmckinfoSubChunk.ckid =mmioFOURCC('f','m','t',' ');
    if(mmioDescend(m_hmmio,&mmckinfoSubChunk,&mmckinfoParent,MMIO_FINDCHUNK))
    {
        printf("Can't find 'fmt' chunk");
        return 0;
    }
    //获得 'fmt '块的大小,申请内存
    dwFmtSize=mmckinfoSubChunk.cksize ;
    m_hFormat=LocalAlloc(LMEM_MOVEABLE,LOWORD(dwFmtSize));
    if(!m_hFormat)
    {
        printf("failed alloc memory");
        return 0;
    }
    lpFormat=(WAVEFORMATEX*)LocalLock(m_hFormat);
    if(!lpFormat)
    {
        printf("failed to lock the memory");
        return 0;
    }
    if((unsigned long)mmioRead(m_hmmio,(HPSTR)lpFormat,dwFmtSize)!=dwFmtSize)
    {
        printf("failed to read format chunk");
        return 0;
    }
    //离开 fmt 块
    mmioAscend(m_hmmio,&mmckinfoSubChunk,0);
    //寻找 'data' 块
    mmckinfoSubChunk.ckid=mmioFOURCC('d','a','t','a');
    if(mmioDescend(m_hmmio,&mmckinfoSubChunk,&mmckinfoParent,MMIO_FINDCHUNK))
    {
        printf("Can't find 'data' chunk");
        return 0;
    }
    //获得 'data'块的大小
    m_dwDataSize=mmckinfoSubChunk.cksize ;
    m_dwDataOffset =mmckinfoSubChunk.dwDataOffset ;
    if(m_dwDataSize==0L)
    {
        printf("no data in the 'data' chunk");
        return 0;
    }
    //为音频数据分配内存
    lpData=new char[m_dwDataSize];
    if(!lpData)
    {
        printf("\ncan not alloc mem");
        return 0;
    }
    if(mmioSeek(m_hmmio,m_dwDataOffset,SEEK_SET)<0)
    {
        printf("Failed to read the data chunk");
        return 0;
    }
//    m_WaveLong=mmioRead(m_hmmio,lpData,SoundLong);
    m_WaveLong=mmioRead(m_hmmio,lpData,m_dwDataSize);
   
    if(m_WaveLong<0)
    {
        printf("Failed to read the data chunk");
        return 0;
    }
    //检查音频设备,返回音频输出设备的性能
    if(waveOutGetDevCaps(WAVE_MAPPER,&pwoc,sizeof(WAVEOUTCAPS))!=0)
    {
        printf("Unable to allocate or lock memory");
        return 0;
    }

    //检查音频输出设备是否能播放指定的音频文件
    DevsNum = WAVE_MAPPER;
    if(waveOutOpen(&hWaveOut,DevsNum,lpFormat,NULL,NULL,CALLBACK_NULL)!=0)
    {
        printf("Failed to OPEN the wave out devices");
//        return 0;
    }
    //准备待播放的数据
    pWaveOutHdr.lpData =(HPSTR)lpData;
    pWaveOutHdr.dwBufferLength =m_WaveLong;
    pWaveOutHdr.dwFlags =0;
	pWaveOutHdr.dwLoops = 10;
    if(waveOutPrepareHeader(hWaveOut,&pWaveOutHdr,sizeof(WAVEHDR))!=0)
    {
        printf("Failed to prepare the wave data buffer");
        return 0;
    }
	printFlags(pWaveOutHdr.dwFlags, "after [waveOutPrepareHeader]");

	pWaveOutHdr.dwFlags |= (WHDR_BEGINLOOP | WHDR_ENDLOOP);
    //播放音频数据文件
    if(waveOutWrite(hWaveOut,&pWaveOutHdr,sizeof(WAVEHDR))!=0)
    {
        printf("Failed to write the wave data buffer");
        return 0;
    }
	printFlags(pWaveOutHdr.dwFlags, "after [waveOutWrite]");
    //关闭音频输出设备,释放内存
//     printf("\npress any key");
//     getchar();
	Sleep(20000);
	printFlags(pWaveOutHdr.dwFlags, "after [Sleep]");

	if(waveOutUnprepareHeader(hWaveOut, &pWaveOutHdr, sizeof(pWaveOutHdr)) != 0)
	{
		printf("Failed to unPrepare the wave data buffer");
        return 0;
	}
	printFlags(pWaveOutHdr.dwFlags, "after [waveOutUnprepareHeader]");

    waveOutReset(hWaveOut);
	printFlags(pWaveOutHdr.dwFlags, "after [waveOutReset]");

    waveOutClose(hWaveOut);
	printFlags(pWaveOutHdr.dwFlags, "after [waveOutClose]");

    LocalUnlock(m_hFormat);
    LocalFree(m_hFormat);
    delete [] lpData;

    return 0;
}
예제 #2
0
// Open
BOOL WaveFile::Open (LPSTR pszFilename)
{
	int done = FALSE;
	WORD cbExtra = 0;
	BOOL fRtn = SUCCESS;    // assume success
	PCMWAVEFORMAT pcmwf;
	char fullpath[_MAX_PATH];

	m_total_uncompressed_bytes_read = 0;
	m_max_uncompressed_bytes_to_read = AS_HIGHEST_MAX;

	int FileSize, FileOffset;

	if ( !cf_find_file_location(pszFilename, CF_TYPE_ANY, fullpath, &FileSize, &FileOffset ))	{
		goto OPEN_ERROR;
	}

	cfp = mmioOpen(fullpath, NULL, MMIO_ALLOCBUF | MMIO_READ);
	if ( cfp == NULL ) {
		goto OPEN_ERROR;
	}

	// Skip the "RIFF" tag and file size (8 bytes)
	// Skip the "WAVE" tag (4 bytes)
	mmioSeek( cfp, 12+FileOffset, SEEK_SET );

	// Now read RIFF tags until the end of file
	uint tag, size, next_chunk;

	while(done == FALSE)	{
		if ( mmioRead(cfp, (char *)&tag, sizeof(uint)) != sizeof(uint) )
			break;

		if ( mmioRead(cfp, (char *)&size, sizeof(uint)) != sizeof(uint) )
			break;

		next_chunk = mmioSeek( cfp, 0, SEEK_CUR );
		next_chunk += size;

		switch( tag )	{
		case 0x20746d66:		// The 'fmt ' tag
			mmioRead( cfp, (char *)&pcmwf, sizeof(PCMWAVEFORMAT) );
			if ( pcmwf.wf.wFormatTag != WAVE_FORMAT_PCM ) {
				mmioRead( cfp, (char *)&cbExtra, sizeof(short) );
			}

			// Allocate memory for WAVEFORMATEX structure + extra bytes
			if ( (m_pwfmt_original = (WAVEFORMATEX *) malloc ( sizeof(WAVEFORMATEX)+cbExtra )) != NULL ){
				Assert(m_pwfmt_original != NULL);
				// Copy bytes from temporary format structure
				memcpy (m_pwfmt_original, &pcmwf, sizeof(pcmwf));
				m_pwfmt_original->cbSize = cbExtra;

				// Read those extra bytes, append to WAVEFORMATEX structure
				if (cbExtra != 0) {
					mmioRead( cfp, (char *)((ubyte *)(m_pwfmt_original) + sizeof(WAVEFORMATEX)), cbExtra );
				}
			}
			else {
				Int3();		// malloc failed
				goto OPEN_ERROR;
			}	
			break;

		case 0x61746164:		// the 'data' tag
			m_nDataSize = size;	// This is size of data chunk.  Compressed if ADPCM.
			m_data_bytes_left = size;
			m_data_offset = mmioSeek( cfp, 0, SEEK_CUR);
			done = TRUE;
			break;

		default:	// unknown, skip it
			break;
		}	// end switch

		mmioSeek( cfp, next_chunk, SEEK_SET );
	}

  	// At this stage, examine source format, and set up WAVEFORATEX structure for DirectSound.
	// Since DirectSound only supports PCM, force this structure to be PCM compliant.  We will
	// need to convert data on the fly later if our souce is not PCM
	switch ( m_pwfmt_original->wFormatTag ) {
		case WAVE_FORMAT_PCM:
			m_wave_format = WAVE_FORMAT_PCM;
			m_wfmt.wBitsPerSample = m_pwfmt_original->wBitsPerSample;
			break;

		case WAVE_FORMAT_ADPCM:
			m_wave_format = WAVE_FORMAT_ADPCM;
			m_wfmt.wBitsPerSample = 16;
			break;

		default:
			nprintf(("SOUND", "SOUND => Not supporting %d format for playing wave files\n"));
			//Int3();
			goto OPEN_ERROR;
			break;

	} // end switch
            
	// Set up the WAVEFORMATEX structure to have the right PCM characteristics
	m_wfmt.wFormatTag = WAVE_FORMAT_PCM;
	m_wfmt.nChannels = m_pwfmt_original->nChannels;
	m_wfmt.nSamplesPerSec = m_pwfmt_original->nSamplesPerSec;
	m_wfmt.cbSize = 0;
	m_wfmt.nBlockAlign = (unsigned short)(( m_wfmt.nChannels * m_wfmt.wBitsPerSample ) / 8);
	m_wfmt.nAvgBytesPerSec = m_wfmt.nBlockAlign * m_wfmt.nSamplesPerSec;

	// Init some member data from format chunk
	m_nBlockAlign = m_pwfmt_original->nBlockAlign;
	m_nUncompressedAvgDataRate = m_wfmt.nAvgBytesPerSec;

	// Cue for streaming
	Cue ();
 
	// Successful open
	goto OPEN_DONE;
    
OPEN_ERROR:
	// Handle all errors here
	nprintf(("SOUND","SOUND ==> Could not open wave file %s for streaming\n",pszFilename));

	fRtn = FAILURE;
	if (cfp != NULL) {
		// Close file
		mmioClose( cfp, 0 );
		cfp = NULL;
	}
	if (m_pwfmt_original)
	{
		free(m_pwfmt_original);
		m_pwfmt_original = NULL;
	}

OPEN_DONE:
	return (fRtn);
}
예제 #3
0
//-----------------------------------------------------------------------------
// 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 WaveDecoder::ReadMMIO()
{
    MMCKINFO ckIn;           // chunk info. for general use.
    PCMWAVEFORMAT pcmWaveFormat;  // Temp PCM structure to load in.

    memset( &ckIn, 0, sizeof(ckIn) );

    m_pwfx = NULL;

    if( ( 0 != mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) ) )
        //return DXTRACE_ERR( L"mmioDescend", E_FAIL );
		return 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( L"mmioFOURCC", E_FAIL );
		return 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( L"mmioDescend", E_FAIL );
		return 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( L"sizeof(PCMWAVEFORMAT)", E_FAIL );
		return E_FAIL;

    // Read the 'fmt ' chunk into <pcmWaveFormat>.
    if( mmioRead( m_hmmio, ( HPSTR )&pcmWaveFormat,
                  sizeof( pcmWaveFormat ) ) != sizeof( pcmWaveFormat ) )
        //return DXTRACE_ERR( L"mmioRead", E_FAIL );
		return 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( L"m_pwfx", E_FAIL );
			return 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( L"mmioRead", E_FAIL );
			return E_FAIL;

        m_pwfx = ( WAVEFORMATEX* )new CHAR[ sizeof( WAVEFORMATEX ) + cbExtraBytes ];
        if( NULL == m_pwfx )
            //return DXTRACE_ERR( L"new", E_FAIL );
			return 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( L"mmioRead", E_FAIL );
			return 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( L"mmioAscend", E_FAIL );
		return E_FAIL;
    }

    return S_OK;
}
예제 #4
0
파일: mmoutput.c 프로젝트: iamfil/wine
static BOOL MCIAVI_GetInfoVideo(WINE_MCIAVI* wma, const MMCKINFO* mmckList, MMCKINFO* mmckStream)
{
    MMCKINFO	mmckInfo;

    TRACE("ash.fccType='%c%c%c%c'\n", 		LOBYTE(LOWORD(wma->ash_video.fccType)),
	                                        HIBYTE(LOWORD(wma->ash_video.fccType)),
	                                        LOBYTE(HIWORD(wma->ash_video.fccType)),
	                                        HIBYTE(HIWORD(wma->ash_video.fccType)));
    TRACE("ash.fccHandler='%c%c%c%c'\n",	LOBYTE(LOWORD(wma->ash_video.fccHandler)),
	                                        HIBYTE(LOWORD(wma->ash_video.fccHandler)),
	                                        LOBYTE(HIWORD(wma->ash_video.fccHandler)),
	                                        HIBYTE(HIWORD(wma->ash_video.fccHandler)));
    TRACE("ash.dwFlags=%d\n", 			wma->ash_video.dwFlags);
    TRACE("ash.wPriority=%d\n", 		wma->ash_video.wPriority);
    TRACE("ash.wLanguage=%d\n", 		wma->ash_video.wLanguage);
    TRACE("ash.dwInitialFrames=%d\n", 		wma->ash_video.dwInitialFrames);
    TRACE("ash.dwScale=%d\n", 			wma->ash_video.dwScale);
    TRACE("ash.dwRate=%d\n", 			wma->ash_video.dwRate);
    TRACE("ash.dwStart=%d\n", 			wma->ash_video.dwStart);
    TRACE("ash.dwLength=%d\n", 		wma->ash_video.dwLength);
    TRACE("ash.dwSuggestedBufferSize=%d\n", 	wma->ash_video.dwSuggestedBufferSize);
    TRACE("ash.dwQuality=%d\n", 		wma->ash_video.dwQuality);
    TRACE("ash.dwSampleSize=%d\n", 		wma->ash_video.dwSampleSize);
    TRACE("ash.rcFrame=(%d,%d,%d,%d)\n", 	wma->ash_video.rcFrame.top, wma->ash_video.rcFrame.left,
	  wma->ash_video.rcFrame.bottom, wma->ash_video.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;
    }

    wma->inbih = HeapAlloc(GetProcessHeap(), 0, mmckInfo.cksize);
    if (!wma->inbih) {
	WARN("Can't alloc input BIH\n");
	return FALSE;
    }

    mmioRead(wma->hFile, (LPSTR)wma->inbih, mmckInfo.cksize);

    TRACE("bih.biSize=%d\n", 		wma->inbih->biSize);
    TRACE("bih.biWidth=%d\n", 		wma->inbih->biWidth);
    TRACE("bih.biHeight=%d\n", 	wma->inbih->biHeight);
    TRACE("bih.biPlanes=%d\n", 		wma->inbih->biPlanes);
    TRACE("bih.biBitCount=%d\n", 	wma->inbih->biBitCount);
    TRACE("bih.biCompression=%x\n", 	wma->inbih->biCompression);
    TRACE("bih.biSizeImage=%d\n", 	wma->inbih->biSizeImage);
    TRACE("bih.biXPelsPerMeter=%d\n", 	wma->inbih->biXPelsPerMeter);
    TRACE("bih.biYPelsPerMeter=%d\n", 	wma->inbih->biYPelsPerMeter);
    TRACE("bih.biClrUsed=%d\n", 	wma->inbih->biClrUsed);
    TRACE("bih.biClrImportant=%d\n", 	wma->inbih->biClrImportant);

    wma->source.left = 0;
    wma->source.top = 0;
    wma->source.right = wma->inbih->biWidth;
    wma->source.bottom = wma->inbih->biHeight;

    wma->dest = wma->source;

    return TRUE;
}
예제 #5
0
파일: AudioFile.cpp 프로젝트: osoumen/C700
//-----------------------------------------------------------------------------
bool AudioFile::Load()
{
#if MAC
	AudioFileID mAudioFileID;
    AudioStreamBasicDescription fileDescription, outputFormat;
    SInt64 dataSize64;
    UInt32 dataSize;
	
	OSStatus err;
	UInt32 size;
	
    // ファイルを開く
	FSRef	ref;
	Boolean	isDirectory=false;
	FSPathMakeRef((const UInt8*)GetFilePath(), &ref, &isDirectory);
	
	err = AudioFileOpen(&ref, fsRdPerm, 0, &mAudioFileID);
    if (err) {
        //NSLog(@"AudioFileOpen failed");
        return false;
    }
	
    // 開いたファイルの基本情報を fileDescription へ
    size = sizeof(AudioStreamBasicDescription);
	err = AudioFileGetProperty(mAudioFileID, kAudioFilePropertyDataFormat, 
							   &size, &fileDescription);
    if (err) {
        //NSLog(@"AudioFileGetProperty failed");
        AudioFileClose(mAudioFileID);
        return false;
    }
	
    // 開いたファイルのデータ部のバイト数を dataSize へ
    size = sizeof(SInt64);
	err = AudioFileGetProperty(mAudioFileID, kAudioFilePropertyAudioDataByteCount, 
							   &size, &dataSize64);
    if (err) {
        //NSLog(@"AudioFileGetProperty failed");
        AudioFileClose(mAudioFileID);
        return false;
    }
	dataSize = static_cast<UInt32>(dataSize64);
	
	AudioFileTypeID	fileTypeID;
	size = sizeof( AudioFileTypeID );
	err = AudioFileGetProperty(mAudioFileID, kAudioFilePropertyFileFormat, &size, &fileTypeID);
	if (err) {
        //NSLog(@"AudioFileGetProperty failed");
        AudioFileClose(mAudioFileID);
        return false;
    }
	
	// Instrument情報を初期化
	mInstData.basekey	= 60;
	mInstData.lowkey	= 0;
	mInstData.highkey	= 127;
	mInstData.loop		= 0;
	
	//ループポイントの取得
	Float64		st_point=0.0,end_point=0.0;
	if ( fileTypeID == kAudioFileAIFFType || fileTypeID == kAudioFileAIFCType ) {
		//INSTチャンクの取得
		AudioFileGetUserDataSize(mAudioFileID, 'INST', 0, &size);
		if ( size > 4 ) {
			UInt8	*instChunk = new UInt8[size];
			AudioFileGetUserData(mAudioFileID, 'INST', 0, &size, instChunk);
			
			//MIDI情報の取得
			mInstData.basekey = instChunk[0];
			mInstData.lowkey = instChunk[2];
			mInstData.highkey = instChunk[3];
			
			if ( instChunk[9] > 0 ) {	//ループフラグを確認
				//マーカーの取得
				UInt32	writable;
				err = AudioFileGetPropertyInfo(mAudioFileID, kAudioFilePropertyMarkerList,
											   &size, &writable);
				if (err) {
					//NSLog(@"AudioFileGetPropertyInfo failed");
					AudioFileClose(mAudioFileID);
					return NULL;
				}
				UInt8	*markersBuffer = new UInt8[size];
				AudioFileMarkerList	*markers = reinterpret_cast<AudioFileMarkerList*>(markersBuffer);
				
				err = AudioFileGetProperty(mAudioFileID, kAudioFilePropertyMarkerList, 
										   &size, markers);
				if (err) {
					//NSLog(@"AudioFileGetProperty failed");
					AudioFileClose(mAudioFileID);
					return NULL;
				}
				
				//ループポイントの設定
				for (unsigned int i=0; i<markers->mNumberMarkers; i++) {
					if (markers->mMarkers[i].mMarkerID == instChunk[11] ) {
						st_point = markers->mMarkers[i].mFramePosition;
					}
					else if (markers->mMarkers[i].mMarkerID == instChunk[13] ) {
						end_point = markers->mMarkers[i].mFramePosition;
					}
					CFRelease(markers->mMarkers[i].mName);
				}
				if ( st_point < end_point ) {
					mInstData.loop = 1;
				}
				delete [] markersBuffer;
			}
			delete [] instChunk;
		}
		
	}
	else if ( fileTypeID == kAudioFileWAVEType ) {
		//smplチャンクの取得
		AudioFileGetUserDataSize( mAudioFileID, 'smpl', 0, &size );
		if ( size >= sizeof(WAV_smpl) ) {
			UInt8	*smplChunk = new UInt8[size];
			AudioFileGetUserData( mAudioFileID, 'smpl', 0, &size, smplChunk );
			WAV_smpl	*smpl = (WAV_smpl *)smplChunk;
			
			smpl->loops = EndianU32_LtoN( smpl->loops );
			
			if ( smpl->loops > 0 ) {
				mInstData.loop = true;
				mInstData.basekey = EndianU32_LtoN( smpl->note );
				st_point = EndianU32_LtoN( smpl->start );
				end_point = EndianU32_LtoN( smpl->end ) + 1;	//SoundForge等では最終ポイントを含める解釈
				//end_point = EndianU32_LtoN( smpl->end );	//PeakではなぜかAIFFと同じ
			}
			else {
				mInstData.basekey = EndianU32_LtoN( smpl->note );
			}
			delete [] smplChunk;
		}
	}
	
	//容量の制限
	SInt64	dataSamples = dataSize / fileDescription.mBytesPerFrame;
	if ( dataSamples > MAXIMUM_SAMPLES ) {
		dataSize = MAXIMUM_SAMPLES * fileDescription.mBytesPerFrame;
	}
	if ( st_point > MAXIMUM_SAMPLES ) {
		st_point = MAXIMUM_SAMPLES;
	}
	if ( end_point > MAXIMUM_SAMPLES ) {
		end_point = MAXIMUM_SAMPLES;
	}
	
    // 波形一時読み込み用メモリを確保
    char *fileBuffer;
	unsigned int	fileBufferSize;
	if (mInstData.loop) {
		fileBufferSize = dataSize+EXPAND_BUFFER*fileDescription.mBytesPerFrame;
	}
	else {
		fileBufferSize = dataSize;
	}
	fileBuffer = new char[fileBufferSize];
	memset(fileBuffer, 0, fileBufferSize);
	
	// ファイルから波形データの読み込み
	err = AudioFileReadBytes(mAudioFileID, false, 0, &dataSize, fileBuffer);
    if (err) {
        //NSLog(@"AudioFileReadBytes failed");
        AudioFileClose(mAudioFileID);
        delete [] fileBuffer;
        return false;
    }
    AudioFileClose(mAudioFileID);
	
    //ループを展開する
    Float64	adjustment = 1.0;
    outputFormat=fileDescription;
	if (mInstData.loop) {
		UInt32	plusalpha=0, framestocopy;
		while (plusalpha < EXPAND_BUFFER) {
			framestocopy = 
			(end_point-st_point)>(EXPAND_BUFFER-plusalpha)?(EXPAND_BUFFER-plusalpha):end_point-st_point;
			memcpy(fileBuffer+((int)end_point+plusalpha)*fileDescription.mBytesPerFrame,
				   fileBuffer+(int)st_point*fileDescription.mBytesPerFrame,
				   framestocopy*fileDescription.mBytesPerFrame);
			plusalpha += framestocopy;
		}
		dataSize += plusalpha*fileDescription.mBytesPerFrame;
		
		//16サンプル境界にFIXする
		adjustment = ( (long long)((end_point-st_point)/16) ) / ((end_point-st_point)/16.0);
		st_point *= adjustment;
		end_point *= adjustment;
	}
	outputFormat.mFormatID = kAudioFormatLinearPCM;
    outputFormat.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagsNativeEndian;
	outputFormat.mChannelsPerFrame = 1;
	outputFormat.mBytesPerFrame = sizeof(float);
	outputFormat.mBitsPerChannel = 32;
	outputFormat.mBytesPerPacket = outputFormat.mBytesPerFrame;
	
    // バイトオーダー変換用のコンバータを用意
    AudioConverterRef converter;
	err = AudioConverterNew(&fileDescription, &outputFormat, &converter);
    if (err) {
        //NSLog(@"AudioConverterNew failed");
        delete [] fileBuffer;
        return false;
    }
	
	//サンプリングレート変換の質を最高に設定
//	if (fileDescription.mSampleRate != outputFormat.mSampleRate) {
//		size = sizeof(UInt32);
//		UInt32	setProp = kAudioConverterQuality_Max;
//		AudioConverterSetProperty(converter, kAudioConverterSampleRateConverterQuality,
//								  size, &setProp);
//        
//        size = sizeof(UInt32);
//		setProp = kAudioConverterSampleRateConverterComplexity_Mastering;
//		AudioConverterSetProperty(converter, kAudioConverterSampleRateConverterComplexity,
//								  size, &setProp);
//        
//	}
	
    //出力に必要十分なバッファサイズを得る
	UInt32	outputSize = dataSize;
	size = sizeof(UInt32);
	err = AudioConverterGetProperty(converter, kAudioConverterPropertyCalculateOutputBufferSize, 
									&size, &outputSize);
	if (err) {
		//NSLog(@"AudioConverterGetProperty failed");
		delete [] fileBuffer;
		AudioConverterDispose(converter);
        return false;
	}
    UInt32 monoSamples = outputSize/sizeof(float);
    
    // バイトオーダー変換
    float *monoData = new float[monoSamples];
	AudioConverterConvertBuffer(converter, dataSize, fileBuffer,
								&outputSize, monoData);
    if(outputSize == 0) {
        //NSLog(@"AudioConverterConvertBuffer failed");
        delete [] fileBuffer;
        AudioConverterDispose(converter);
        return false;
    }
    
    //ループ長が16の倍数でない場合はサンプリングレート変換
    Float64 inputSampleRate = fileDescription.mSampleRate;
    Float64 outputSampleRate = fileDescription.mSampleRate * adjustment;
    int	outSamples = monoSamples;
    if ( outputSampleRate == inputSampleRate ) {
        m_pAudioData = new short[monoSamples];
        for (int i=0; i<monoSamples; i++) {
            m_pAudioData[i] = static_cast<short>(monoData[i] * 32768);
        }
    }
    else {
        outSamples = static_cast<int>(monoSamples / (inputSampleRate / outputSampleRate));
        m_pAudioData = new short[outSamples];
        resampling(monoData, monoSamples, inputSampleRate,
                   m_pAudioData, &outSamples, outputSampleRate);
    }
    
    // 後始末
    delete [] monoData;
    delete [] fileBuffer;
    AudioConverterDispose(converter);
	
	//Instデータの設定
	if ( st_point > MAXIMUM_SAMPLES ) {
		mInstData.lp = MAXIMUM_SAMPLES;
	}
	else {
		mInstData.lp			= st_point;
	}
	if ( end_point > MAXIMUM_SAMPLES ) {
		mInstData.lp_end = MAXIMUM_SAMPLES;
	}
	else {
		mInstData.lp_end		= end_point;
	}
	mInstData.srcSamplerate	= outputSampleRate;
    mLoadedSamples			= outSamples;
	
	mIsLoaded = true;
	
	return true;
#else
	//Windowsのオーディオファイル読み込み処理

	// ファイルを開く
	HMMIO	hmio = NULL;
	MMRESULT	err;
	DWORD		size;

	hmio = mmioOpen( mPath, NULL, MMIO_READ );
	if ( !hmio ) {
		return false;
	}
	
	// RIFFチャンクを探す
	MMCKINFO	riffChunkInfo;
	riffChunkInfo.fccType = mmioFOURCC('W', 'A', 'V', 'E');
	err = mmioDescend( hmio, &riffChunkInfo, NULL, MMIO_FINDRIFF );
	if ( err != MMSYSERR_NOERROR ) {
		mmioClose( hmio, 0 );
		return false;
	}
	if ( (riffChunkInfo.ckid != FOURCC_RIFF) || (riffChunkInfo.fccType != mmioFOURCC('W', 'A', 'V', 'E') ) ) {
		mmioClose( hmio, 0 );
		return false;
	}

	// フォーマットチャンクを探す
	MMCKINFO	formatChunkInfo;
	formatChunkInfo.ckid = mmioFOURCC('f', 'm', 't', ' ');
	err = mmioDescend( hmio, &formatChunkInfo, &riffChunkInfo, MMIO_FINDCHUNK );
	if ( err != MMSYSERR_NOERROR ) {
		mmioClose( hmio, 0 );
		return false;
	}
	if ( formatChunkInfo.cksize < sizeof(PCMWAVEFORMAT) ) {
		mmioClose( hmio, 0 );
		return false;
	}

	//フォーマット情報を取得
	WAVEFORMATEX	pcmWaveFormat;
	DWORD			fmsize = (formatChunkInfo.cksize > sizeof(WAVEFORMATEX)) ? sizeof(WAVEFORMATEX):formatChunkInfo.cksize;
	size = mmioRead( hmio, (HPSTR)&pcmWaveFormat, fmsize );
	if ( size != fmsize ) {
		mmioClose( hmio, 0 );
		return false;
	}
	if ( pcmWaveFormat.wFormatTag != WAVE_FORMAT_PCM ) {
		mmioClose( hmio, 0 );
		return false;
	}
	mmioAscend(hmio, &formatChunkInfo, 0);

	// Instrument情報を初期化
	mInstData.basekey	= 60;
	mInstData.lowkey	= 0;
	mInstData.highkey	= 127;
	mInstData.loop		= 0;

	//smplチャンクを探す
	MMCKINFO	smplChunkInfo;
	smplChunkInfo.ckid = mmioFOURCC('s', 'm', 'p', 'l');
	err = mmioDescend( hmio, &smplChunkInfo, &riffChunkInfo, MMIO_FINDCHUNK );
	if ( err != MMSYSERR_NOERROR ) {
		smplChunkInfo.cksize = 0;
	}
	double	st_point=0.0;
	double	end_point=0.0;
	if ( smplChunkInfo.cksize >= sizeof(WAV_smpl) ) {
		//ループポイントの取得
		unsigned char	*smplChunk = new unsigned char[smplChunkInfo.cksize];
		size = mmioRead(hmio,(HPSTR)smplChunk, smplChunkInfo.cksize);
		WAV_smpl	*smpl = (WAV_smpl *)smplChunk;

		if ( smpl->loops > 0 ) {
			mInstData.loop = 1;
			mInstData.basekey = smpl->note;
			st_point = smpl->start;
			end_point = smpl->end + 1;	//SoundForge等では最終ポイントを含める解釈
		}
		else {
			mInstData.basekey = smpl->note;
		}
		delete [] smplChunk;
	}
	mmioAscend(hmio, &formatChunkInfo, 0);

	//dataチャンクを探す
	MMCKINFO dataChunkInfo;
	dataChunkInfo.ckid = mmioFOURCC('d', 'a', 't', 'a');
	err = mmioDescend( hmio, &dataChunkInfo, &riffChunkInfo, MMIO_FINDCHUNK );
	if( err != MMSYSERR_NOERROR ) {
		mmioClose( hmio, 0 );
		return false;
	}

	// 波形一時読み込み用メモリを確保
	unsigned int	dataSize = dataChunkInfo.cksize;
	int				bytesPerSample = pcmWaveFormat.nBlockAlign;
	char			*fileBuffer;
	unsigned int	fileBufferSize;

	//容量制限
	int	dataSamples = dataSize / pcmWaveFormat.nBlockAlign;
	if ( dataSamples > MAXIMUM_SAMPLES ) {
		dataSize = MAXIMUM_SAMPLES * pcmWaveFormat.nBlockAlign;
	}
	if ( st_point > MAXIMUM_SAMPLES ) {
		st_point = MAXIMUM_SAMPLES;
	}
	if ( end_point > MAXIMUM_SAMPLES ) {
		end_point = MAXIMUM_SAMPLES;
	}
	
	
	if (mInstData.loop) {
		fileBufferSize = dataSize+EXPAND_BUFFER*bytesPerSample;
	}
	else {
		fileBufferSize = dataSize;
	}
	fileBuffer = new char[fileBufferSize];
	memset(fileBuffer, 0, fileBufferSize);
	
	// ファイルから波形データの読み込み
	size = mmioRead(hmio, (HPSTR)fileBuffer, dataSize);
	if ( size != dataSize ) {
		mmioClose( hmio, 0 );
		return false;
	}
	mmioClose(hmio,0);

	//ループを展開する
	double	inputSampleRate = pcmWaveFormat.nSamplesPerSec;
	double	outputSampleRate = inputSampleRate;
	if (mInstData.loop) {
		unsigned int	plusalpha=0;
		double			framestocopy;
		while (plusalpha < EXPAND_BUFFER) {
			framestocopy = 
			(end_point-st_point)>(EXPAND_BUFFER-plusalpha)?(EXPAND_BUFFER-plusalpha):end_point-st_point;
			memcpy(fileBuffer+((int)end_point+plusalpha)*bytesPerSample,
				   fileBuffer+(int)st_point*bytesPerSample,
				   static_cast<size_t>(framestocopy*bytesPerSample));
			plusalpha += static_cast<unsigned int>(framestocopy);
		}
		dataSize += plusalpha*bytesPerSample;
		
		//16サンプル境界にFIXする
		double	adjustment = ( (long long)((end_point-st_point)/16) ) / ((end_point-st_point)/16.0);
		outputSampleRate *= adjustment;
		st_point *= adjustment;
		end_point *= adjustment;
	}

	//一旦floatモノラルデータに変換
	int	bytesPerChannel = bytesPerSample / pcmWaveFormat.nChannels;
	unsigned int	inputPtr = 0;
	unsigned int	outputPtr = 0;
	int				monoSamples = dataSize / bytesPerSample;
	float	range = static_cast<float>((1<<(bytesPerChannel*8-1)) * pcmWaveFormat.nChannels);
	float	*monoData = new float[monoSamples];
	while (inputPtr < dataSize) {
		int	frameSum = 0;
		for (int ch=0; ch<pcmWaveFormat.nChannels; ch++) {
			for (int i=0; i<bytesPerChannel; i++) {
				if (i<bytesPerChannel-1) {
					frameSum += (unsigned char)fileBuffer[inputPtr] << (8*i);
				}
				else {
					frameSum += fileBuffer[inputPtr] << (8*i);
				}
				inputPtr++;
			}
		}
		monoData[outputPtr] = frameSum / range;
		outputPtr++;
	}

	//ループ長が16の倍数でない場合はサンプリングレート変換
	int	outSamples = monoSamples;
	if ( outputSampleRate == inputSampleRate ) {
		m_pAudioData = new short[monoSamples];
		for (int i=0; i<monoSamples; i++) {
			m_pAudioData[i] = static_cast<short>(monoData[i] * 32768);
		}
	}
	else {
		outSamples = static_cast<int>(monoSamples / (inputSampleRate / outputSampleRate));
		m_pAudioData = new short[outSamples];
		resampling(monoData, monoSamples, inputSampleRate,
				   m_pAudioData, &outSamples, outputSampleRate);
	}

	// 後始末
	delete [] fileBuffer;
	delete [] monoData;

	//Instデータの設定
	mInstData.lp			= static_cast<int>(st_point);
	mInstData.lp_end		= static_cast<int>(end_point);
	mInstData.srcSamplerate	= outputSampleRate;
    mLoadedSamples			= outSamples;

	mIsLoaded = true;

	return true;
#endif
}
예제 #6
0
//-----------------------------------------------------------------------------
// Name: ReadMMIO()
// Desc: Support function for reading from a multimedia I/O stream
//-----------------------------------------------------------------------------
HRESULT ReadMMIO(HMMIO hmmioIn, MMCKINFO* pckInRIFF, WAVEFORMATEX** ppwfxInfo)
{
   MMCKINFO        ckIn;           // chunk info. for general use.
   PCMWAVEFORMAT   pcmWaveFormat;  // Temp PCM structure to load in.       

   *ppwfxInfo = NULL;

   if ((0 != mmioDescend(hmmioIn, pckInRIFF, NULL, 0)))
      return E_FAIL;

   if ((pckInRIFF->ckid != FOURCC_RIFF) ||
      (pckInRIFF->fccType != mmioFOURCC('W', 'A', 'V', 'E')))
      return E_FAIL;

   // Search the input file for for the 'fmt ' chunk.
   ckIn.ckid = mmioFOURCC('f', 'm', 't', ' ');
   if (0 != mmioDescend(hmmioIn, &ckIn, pckInRIFF, MMIO_FINDCHUNK))
      return 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 E_FAIL;

   // Read the 'fmt ' chunk into <pcmWaveFormat>.
   if (mmioRead(hmmioIn, (HPSTR)&pcmWaveFormat,
      sizeof(pcmWaveFormat)) != sizeof(pcmWaveFormat))
      return 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)
   {
      if (NULL == (*ppwfxInfo = new WAVEFORMATEX))
         return E_FAIL;

      // Copy the bytes from the pcm structure to the waveformatex structure
      memcpy(*ppwfxInfo, &pcmWaveFormat, sizeof(pcmWaveFormat));
      (*ppwfxInfo)->cbSize = 0;
   }
   else
   {
      // Read in length of extra bytes.
      WORD cbExtraBytes = 0L;
      if (mmioRead(hmmioIn, (CHAR*)&cbExtraBytes, sizeof(WORD)) != sizeof(WORD))
         return E_FAIL;

      *ppwfxInfo = (WAVEFORMATEX*)new CHAR[sizeof(WAVEFORMATEX) + cbExtraBytes];
      if (NULL == *ppwfxInfo)
         return E_FAIL;

      // Copy the bytes from the pcm structure to the waveformatex structure
      memcpy(*ppwfxInfo, &pcmWaveFormat, sizeof(pcmWaveFormat));
      (*ppwfxInfo)->cbSize = cbExtraBytes;

      // Now, read those extra bytes into the structure, if cbExtraAlloc != 0.
      if (mmioRead(hmmioIn, (CHAR*)(((BYTE*)&((*ppwfxInfo)->cbSize)) + sizeof(WORD)),
         cbExtraBytes) != cbExtraBytes)
      {
         delete *ppwfxInfo;
         *ppwfxInfo = NULL;
         return E_FAIL;
      }
   }

   // Ascend the input file out of the 'fmt ' chunk.
   if (0 != mmioAscend(hmmioIn, &ckIn, 0))
   {
      delete *ppwfxInfo;
      *ppwfxInfo = NULL;
      return E_FAIL;
   }

   return S_OK;
}
예제 #7
0
int CWavFile::CheckValidity(HMMIO& hWaveFile, CString strFilePath, WAVEFORMATEX& wfx)
{
	MMRESULT mmResult = 0;
	DWORD dwFmtSize = 0;
	LPTSTR pszFilePath = strdup(strFilePath);

	hWaveFile = mmioOpen(pszFilePath, NULL, MMIO_READ);
	if(hWaveFile == NULL)
	{
		MyMessageBox(_T("Open the wav file failed"), eERR_INFO);
		return -1;
	}

	// Descend 'wave' chunk
	m_mmckinfoParent.fccType = mmioFOURCC('W','A','V','E');
	mmResult = mmioDescend(hWaveFile, &m_mmckinfoParent, NULL, MMIO_FINDRIFF);
	if(mmResult)
	{
		MyMessageBox(_T("It is not a wave format file"), eERR_INFO);
		return -1;
	}

	// Desecnd 'fmt ' chunk
	m_mmckinfoSubChunk.ckid = mmioFOURCC('f', 'm', 't', ' ');
	mmResult = mmioDescend(hWaveFile, &m_mmckinfoSubChunk, &m_mmckinfoParent, MMIO_FINDCHUNK);
	if(mmResult)
	{
		MyMessageBox(_T("Can't find the fmt chunk"), eERR_INFO);
		return -1;
	}

	// Read 'fmt ' chunk
	dwFmtSize = m_mmckinfoSubChunk.cksize;
	if((unsigned long)mmioRead(hWaveFile, (HPSTR)&wfx, dwFmtSize) != dwFmtSize)
	{
		MyMessageBox(_T("Read format chunk failed"), eERR_INFO);
		return -1;
	}
	
	// Ascend the 'fmt ' chunk
	mmResult = mmioAscend(hWaveFile, &m_mmckinfoSubChunk, 0);
	if(mmResult)
	{
		MyMessageBox(_T("Ascend fmt chunk failed"), eERR_INFO);
		return -1;
	}

	// Descend the 'data' chunk
	m_mmckinfoSubChunk.ckid = mmioFOURCC('d','a','t','a');
	mmResult = mmioDescend(hWaveFile, &m_mmckinfoSubChunk, &m_mmckinfoParent, MMIO_FINDCHUNK);
	if(mmResult)
	{
		MyMessageBox(_T("Cannot find data chunk"), eERR_INFO);
		return -1;
	}
	else
	{
		m_dwDataSize = m_mmckinfoSubChunk.cksize;
	}
	
	return m_dwDataSize;
}
/*************************************************************************
 * Name         : PlayTheWave
 *
 * Description : This function initially opens the wave file to be played
 *               and tells the MCD information about the file
 *               that is about to be played.  The Samples Per Second,
 *               Bits Per Sample, and the number of channels with which
 *               the waveform file was created has to be told to the MCD.
 *               This function initially fills up the allocated buffer
 *               of the playlist with the wave file.  For 0 - MAXBUFF
 *               the wave file is filled into the memory.  The Wave file
 *               is read in continously from 0 -MAXBUFF.
 *               This same buffer is dynamically re-filled again and again
 *               by the PlayThread thread.
 *
 * Concepts     : The wave file is first opened and then continuously read
 *                into the buffer.  If the end of the wave file is reached
 *                then we seek to the starting of the wave and keep on reading
 *                the wave file till the buffer fills up. This displays the
 *                double buffering concept because, while the playlist is
 *                continuously looping and playing the wave file, the
 *                playlist buffers are constantly being filled with data from
 *                the wave file in the PlayThread thread.
 *
 *
 *
 * MMPM/2 API's : mmioOpen
 *                mmioGetHeader
 *                mmioRead
 *                mmioSeek
 *                mciSendCommand
 *                  MCI_SET
 *                  MCI_CUE
 *
 * Parameters   : None.
 *
 * Return       : ulReturn
 *
 *************************************************************************/
ULONG PlayTheWave()
{

   MCI_WAVE_SET_PARMS    lpWaveSet;
   ULONG                 ulReturn;
   MMAUDIOHEADER         mmHeader;
   int i;
   long                  ulBytesRead;


   memset ( &lpWaveSet,
            0,
            sizeof( MCI_WAVE_SET_PARMS ) );

   /* Open the Wave File MyWave.Wav for Reading */
   hmmioFileHandle = mmioOpen(WAVE_FILE_NAME,
                             (PMMIOINFO) NULL,
                             MMIO_READ);

   /* If the Wave File could not be opened */
   if (!hmmioFileHandle)
      {

      ShowAMessage(
         IDS_ERROR_TITLE,
         IDS_CANT_OPEN_WAVE,
         MB_OK | MB_INFORMATION | MB_MOVEABLE | MB_HELP |
         MB_APPLMODAL,
         FALSE );

      return ( TRUE );
      }

   /*
    * Get the Header Information for the file so that we can set the channels,
    * Samples Per Second and Bits Per Sample to play the memory playlist.
    */

   ulReturn = mmioGetHeader(hmmioFileHandle,
                            (PVOID) &mmHeader,
                            sizeof(MMAUDIOHEADER),
                            (PLONG) &ulBytesRead,
                            (ULONG) NULL,
                            (ULONG) NULL);
   if (ulReturn != 0 )
     return ( ulReturn );

   /* Set the WaveSet Structure */

   lpWaveSet.ulLevel = 100;
   lpWaveSet.ulSamplesPerSec = mmHeader.mmXWAVHeader.WAVEHeader.ulSamplesPerSec;
   lpWaveSet.usBitsPerSample = mmHeader.mmXWAVHeader.WAVEHeader.usBitsPerSample;
   lpWaveSet.usChannels = mmHeader.mmXWAVHeader.WAVEHeader.usChannels;
   lpWaveSet.ulAudio = MCI_SET_AUDIO_ALL;
   lpWaveSet.hwndCallback = (HWND) NULL;

   /* Set the Channels for the MCD */
   ulReturn
        = mciSendCommand(usWaveDeviceId,
                         MCI_SET,
                         MCI_WAIT | MCI_WAVE_SET_CHANNELS,
                         (PVOID) &lpWaveSet,
                         (USHORT)NULL);
   if (ulReturn != 0 )
     return ( ulReturn );

   /* Set the Samples Per Second */
   ulReturn
        = mciSendCommand(usWaveDeviceId,
                         MCI_SET,
                         MCI_WAIT | MCI_WAVE_SET_SAMPLESPERSEC,
                         (PVOID) &lpWaveSet,
                         (USHORT)NULL);

   if (ulReturn != 0 )
     return ( ulReturn );

   /* Set the Bits per Sample */
   ulReturn
        = mciSendCommand(usWaveDeviceId,
                         MCI_SET,
                         MCI_WAIT | MCI_WAVE_SET_BITSPERSAMPLE,
                         (PVOID) &lpWaveSet,
                         (USHORT)NULL);

   if (ulReturn != 0 )
     return ( ulReturn );


  /* From 0 - MAXBUFF, fill the memory Playlist buffer with the wave file. */

   for (i=0; i<MAXBUFF; i++)
   {

     ulBytesRead =
           mmioRead(hmmioFileHandle,
                    (HPSTR) achDataBuffer[i],
                    MAXSIZE);
     /*
      * If the end of the wave file is reached then Seek to the starting
      * of the wave file and start reading the wave into the appropriate
      * buffer
     */
     if (ulBytesRead < MAXSIZE)
        {
         mmioSeek(hmmioFileHandle, 0, SEEK_SET);

         ulBytesRead =
           mmioRead(hmmioFileHandle,
                    (HPSTR) achDataBuffer[i],
                    MAXSIZE);
         }


   }


   /*
    * Create the thread that will maintain the playlist buffer
    */
   fEndPlay = FALSE;
   if ( DosCreateThread ( &tidPlayThread,
                         (PFNTHREAD) PlayThread,
                         0L, 0L, 8192L))
      return ( TRUE );

   return ( FALSE );

}
예제 #9
0
파일: Sound.cpp 프로젝트: bmer/Alchemy
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;
	}
예제 #10
0
BOOL CAudioCtrl::OpenWaveFile(char *lpszWaveFileName)
{
	if ( m_hWaveFile[ENUM_FILE_CHANNEL_COMMON] ) return FALSE; 
	
	m_hWaveFile[ENUM_FILE_CHANNEL_COMMON] = ::mmioOpen ( (LPTSTR)lpszWaveFileName,NULL,MMIO_READ );
	if ( m_hWaveFile[ENUM_FILE_CHANNEL_COMMON] == NULL ) 
	{
		AfxMessageBox ( "Open wave file failed" );
		return FALSE;
	}
	
	m_MMCKInfoParent[ENUM_FILE_CHANNEL_COMMON].fccType = mmioFOURCC('W','A','V','E');
	MMRESULT mmResult = ::mmioDescend(m_hWaveFile[ENUM_FILE_CHANNEL_COMMON], &m_MMCKInfoParent[ENUM_FILE_CHANNEL_COMMON],NULL,MMIO_FINDRIFF);
	if(mmResult)
	{
		AfxMessageBox("Error descending into file");
		::mmioClose(m_hWaveFile[ENUM_FILE_CHANNEL_COMMON],0);
		m_hWaveFile[ENUM_FILE_CHANNEL_COMMON] = NULL;
		return FALSE;
	}
	m_MMCKInfoChild[ENUM_FILE_CHANNEL_COMMON].ckid = mmioFOURCC('f','m','t',' ');
	mmResult = mmioDescend(m_hWaveFile[ENUM_FILE_CHANNEL_COMMON],&m_MMCKInfoChild[ENUM_FILE_CHANNEL_COMMON],&m_MMCKInfoParent[ENUM_FILE_CHANNEL_COMMON],MMIO_FINDCHUNK);
	if(mmResult)
	{
		AfxMessageBox("Error descending in wave file");
		mmioClose(m_hWaveFile[ENUM_FILE_CHANNEL_COMMON],0);
		m_hWaveFile[ENUM_FILE_CHANNEL_COMMON] = NULL;
		return FALSE;
	}
	
	DWORD bytesRead = mmioRead ( m_hWaveFile[ENUM_FILE_CHANNEL_COMMON],(LPSTR)&m_Format, m_MMCKInfoChild[ENUM_FILE_CHANNEL_COMMON].cksize );
	if ( bytesRead < 0 )
	{
		AfxMessageBox ( "Error reading PCM wave format record" );
		mmioClose ( m_hWaveFile[ENUM_FILE_CHANNEL_COMMON], 0 );
		return FALSE;
	}
	if ( !SetRelateParaAfterGetWaveFormat () )
		return FALSE;
	
	// open output sound file
	mmResult = mmioAscend ( m_hWaveFile[ENUM_FILE_CHANNEL_COMMON], &m_MMCKInfoChild[ENUM_FILE_CHANNEL_COMMON], 0 );
	if ( mmResult )
	{
		AfxMessageBox ( "Error ascending in File" );
		mmioClose ( m_hWaveFile[ENUM_FILE_CHANNEL_COMMON], 0 );
		m_hWaveFile[ENUM_FILE_CHANNEL_COMMON] = NULL;
		return FALSE;
	}
	m_MMCKInfoChild[ENUM_FILE_CHANNEL_COMMON].ckid = mmioFOURCC('d','a','t','a');
	mmResult = mmioDescend ( m_hWaveFile[ENUM_FILE_CHANNEL_COMMON], &m_MMCKInfoChild[ENUM_FILE_CHANNEL_COMMON], &m_MMCKInfoParent[ENUM_FILE_CHANNEL_COMMON], MMIO_FINDCHUNK );
	if ( mmResult )
	{
		AfxMessageBox("error reading data chunk");
		mmioClose(m_hWaveFile[ENUM_FILE_CHANNEL_COMMON],0);
		m_hWaveFile[ENUM_FILE_CHANNEL_COMMON] = NULL;
		return FALSE;
	}
	
	return TRUE;
}
VOID  APIENTRY PlayThread ( ULONG parm1 )
{

   ULONG    ulBytesRead;
   ULONG    ulBufferNum;
   ULONG    ulPostCount;
   ULONG    ulReturn;
   MCI_PLAY_PARMS        mciPlayParameters;



   mciPlayParameters.hwndCallback =  hwndDiag;

   /*
    * Send the Play Command to begin the playing of the memory playlist.
    */
   ulReturn = mciSendCommand(usWaveDeviceId,
                             MCI_PLAY,
                             MCI_NOTIFY,
                             (PVOID) &mciPlayParameters,
                             0);

   /*
    * Loop until the playlist is stopped.
    */
   while( !fEndPlay )
   {

      for( ulBufferNum = 0; ulBufferNum < MAXBUFF; ulBufferNum++ )
      {

         /*
          * Use DosWaitEventSem to pause util the playlist plays this
          * buffer. Then refill the buffer and post the semaphore.
          */
         ulReturn = DosWaitEventSem ( hevSem[ulBufferNum], 5000L );

         DosResetEventSem ( hevSem[ulBufferNum], &ulPostCount );

         if( fEndPlay ) break;

            /*
             * Read the Next MAXSIZE bytes of the wave file
             */
            ulBytesRead =
                   mmioRead(hmmioFileHandle,
                            (HPSTR) achDataBuffer[ulBufferNum],
                            MAXSIZE);


            /*
             * If we have reached the end of the wave file then set the file marker
             * to the begining of the file and start reading into the bufferno.
             * This causes the continuous filling and playing of the data buffer
             * again and again as long as the END push button is not pressed.
             * The wave file is going to keep on playing without any interruptions
             * util ther user selects the stop button.
             */
            if (ulBytesRead < MAXSIZE)
              {
               /* Seek to the starting of the wave file */
               mmioSeek(hmmioFileHandle, 0, SEEK_SET);

               /* Read the Next MAXSIZE bytes of the wave file */
               mmioRead(hmmioFileHandle,
                       (HPSTR) achDataBuffer[ulBufferNum],
                       MAXSIZE);


              }


      } /* End of for loop */


   } /* End of while loop */


}   /* End of function PlayThread */
LONG APIENTRY CONVProc( PVOID pmmioStr,
                        USHORT  usMsg,
                        LONG lParam1,
                        LONG lParam2 )

{
   PCONVPROCINFO pInfo;             // Converter I/O Procedure Info Block
   PMMIOINFO pmmioinfo;             // I/O information block
   MMIOINFO mmioinfoSS;             // I/O info block for Storage System
   PMMFORMATINFO pmmformatinfo;     // formatinfo for this ioproc.
   PCONVHEADERINFO pconvHeaderInfo; // pointer to header struct for FFT files.
   PSZ pszFileName;                 // file name passed in from caller
   PSZ pszFormatString;             // format string to return.
   PSZ pszData;
   CHAR szHeaderLength[2];          // storage for header length (USHORT)
   PCHAR pTemp;                     // temp pointer for use in Header manip.
   HFILE hFileHandle;               // file handle created or passed in
   HMMIO hmmioSS;                   // handle for Storage System
   FOURCC fccStorageSystem;         // SS I/O Proc FOURCC
   USHORT usReturnCode;             // return code from mmioClose
   ULONG ulReturnCode;              // return code from mmio API calls
   LONG lReturnCode;                // return code from mmio API calls
   LONG lBytesCopied;               // num of bytes of format string.
   LONG lBytesRead;                 // return from mmioRead
   LONG lBytesWritten;              // return from mmioWrite
   LONG lHeaderLength;              // storage for CONV header length input
   LONG lFilePosition;              // return from mmioSeek
   LONG lSavedFilePosition;         // saved LFP for the file.
   ULONG ulTempFlags;               // temp flags for flags to be removed.

   /*
    *  Initalize local file handle and Return Codes.
    */

   hFileHandle = 0L;
   ulReturnCode = 0L;
   usReturnCode = 0;

   /*
    * Clear the error return before anything happens to insure valid results.
    */

   if (pmmioStr)
      {
      pmmioinfo = (PMMIOINFO) pmmioStr;
      pInfo = (PCONVPROCINFO) &pmmioinfo->aulInfo;
      pmmioinfo->ulErrorRet = MMIO_SUCCESS;
      }
   else
      {
      pmmioinfo = NULL;
      pInfo = NULL;
      }

   /*
    *  Route the MMIO message to the proper code handler.
    */

   switch( usMsg )
      {
      case MMIOM_OPEN:

         /*
          * Get the filename from parameter. Then create a File Format header
          * in memory since this message will use this structure.
          */

         pszFileName = (CHAR *)lParam1;
         pconvHeaderInfo =
            (PCONVHEADERINFO)HhpAllocBuffer( sizeof(CONVHEADERINFO), 0);
         if (!pconvHeaderInfo)
            {
            return (MMIO_ERROR);
            }

         /*
          * If no Storage System I/O proc was determined from mmioOpen,
          * either determine the SS from the name (CREATE case) or
          * search I/O proc list for SS type. If the file is being created
          * and the storage system cannot be determined from the name,
          * default the storage system to DOS.
          */

         if (!pmmioinfo->fccChildIOProc)
            {
            /*
             * Since no Storage system has been determined from mmioOpen, we
             * need to determine the Storage system from the filename. If
             * it cannot be determined from the name, since it's a create we
             * will default the storage system to DOS.
             */

            if (pmmioinfo->ulFlags & MMIO_CREATE)
               {
               if (mmioDetermineSSIOProc( pszFileName,
                                          pmmioinfo,
                                          &fccStorageSystem,
                                          NULL ))
                  {
                  fccStorageSystem = FOURCC_DOS;
                  }
               }
            else
               {

               /*
                * The file already exists, so we need to determine the storage
                * system by looping through all the SS I/O procs until the SS
                * is determined or it is not. If it is not then this file
                * cannot be opened, so return an error.
                */

               if (mmioIdentifyStorageSystem( pszFileName,
                                              pmmioinfo,
                                              &fccStorageSystem ))
                  {
                  return (MMIO_ERROR);
                  }
               }

            /*
             * Now we either have a SS, and if so assign it to the SS I/O
             * proc field of the pmmioinfo sent in, or we don't so return.
             */

            if (!fccStorageSystem)
               {
               return (MMIO_ERROR);
               }
            else
               {
               pmmioinfo->fccChildIOProc = fccStorageSystem;
               }
            }

         /*
          * We have the Storage System FOURCC so open the SS.
          * To set up the mmioOpen call to the storage system :
          *
          *  1. Initialize the mmioinfo passed in for the Storage System.
          *  2. Set fccIOProc to the Storage System FOURCC.
          *  3. Save the hmmcf handle in aulInfo[1] if sent in.
          *  4. IMPORTANT: Use flags sent in EXCEPT Buffered I/O flags.
          *     VERY IMPORTANT: Set the NOIDENTIFY flag before calling the
          *     mmioOpen below to avoid and endless loop.
          *  5. The open call will handle the DELETE flag.
          *  6. Use the name passed in to this I/O proc for the open because
          *     at this point the SS I/O proc will know how to deal with it.
          */

         memset( &mmioinfoSS, '\0', sizeof(MMIOINFO));
         mmioinfoSS.fccIOProc = pmmioinfo->fccChildIOProc;
         memmove( &mmioinfoSS.aulInfo, pmmioinfo->aulInfo,(4*sizeof(ULONG)));
         mmioinfoSS.ulFlags = pmmioinfo->ulFlags;

         ulTempFlags = (MMIO_CREATE|MMIO_READ|MMIO_WRITE|MMIO_READWRITE|
                        MMIO_COMPAT|MMIO_EXCLUSIVE|MMIO_DENYWRITE|
                        MMIO_DENYREAD|MMIO_DENYNONE|MMIO_DELETE|MMIO_VERTBAR|
                        MMIO_APPEND|MMIO_USE_TEMP|MMIO_RWMODE|MMIO_SHAREMODE|
                        MMIO_NOTRANSLATE|MMIO_TRANSLATEDATA|
                        MMIO_TRANSLATEHEADER);

         mmioinfoSS.ulFlags &= ulTempFlags;
         mmioinfoSS.ulFlags |= MMIO_NOIDENTIFY;

         hmmioSS = mmioOpen( pszFileName, &mmioinfoSS, mmioinfoSS.ulFlags );

         if (hmmioSS)
            {
            /*
             * Handle a DELETE request for the file format by returning
             * success if ( hmmio = TRUE = 1).
             */

            if (pmmioinfo->ulFlags & MMIO_DELETE)
               {
               return (MMIO_SUCCESS);
               }
            pInfo->hmmioSS = hmmioSS;
            }
         else
            {
            return (mmioinfoSS.ulErrorRet);
            }

         /*
          * Get the header for the file if it already exists and
          * store it with the MMIOINFO for the file.
          */

         if (!(pmmioinfo->ulFlags & MMIO_CREATE))
            {
            /*
             * Seek the file to the beginning to read in the header.
             */

            lFilePosition = mmioSeek( hmmioSS,
                                      0L,
                                      SEEK_SET );

            if (lFilePosition < 0L)
               {
               mmioClose( hmmioSS, 0L );
               return (MMIO_ERROR);
               }

            /*
             * Read the header of the file into the provided buffer for the
             * given length.
             */

            lBytesRead = mmioRead( hmmioSS,
                                   (PSZ)pconvHeaderInfo,
                                   sizeof(CONVHEADERINFO) );

            if (lBytesRead < 0L)
               {
               mmioClose( hmmioSS, 0L );
               return (MMIO_ERROR);
               }
            }
         else
            {
            /*
             * Make a new header for the file and write it to the beginning.
             */

            pconvHeaderInfo->ulHeaderLength = sizeof(CONVHEADERINFO);
            strcpy( pconvHeaderInfo->szHeaderText, HEADER_STRING );

            lFilePosition = mmioSeek( hmmioSS,
                                      0L,
                                      SEEK_SET );

            if (lFilePosition < 0L)
               {
               mmioClose( hmmioSS, 0L );
               return (MMIO_ERROR);
               }

            /*
             * Write the newly created header to the file.
             */

            lBytesWritten = mmioWrite( hmmioSS,
                                       (PSZ)pconvHeaderInfo,
                                       sizeof(CONVHEADERINFO) );

            if (lBytesWritten < 0L)
               {
               mmioClose( hmmioSS, 0L );
               return (MMIO_ERROR);
               }
            }

         pconvHeaderInfo->ulFlags = 0;
         pmmioinfo->pExtraInfoStruct = (PVOID)pconvHeaderInfo;

         /*
          * Seek the file past the header to allow reads/writes to occur
          * at the first byte of non-header data if the file already exists.
          */

         lReturnCode = mmioSeek( hmmioSS,
                                 sizeof(CONVHEADERINFO),
                                 SEEK_SET );

         if (lReturnCode >= 0L)
            {
            pmmioinfo->lLogicalFilePos = lReturnCode;
            }
         else
            {
            mmioClose( hmmioSS, 0L );
            return (lReturnCode);
            }

         return (0L);

         break;

      case MMIOM_READ:
         /*
          * Call the read API with the Storage System handle using the
          * parameters that have been passed in to this I/O proc.
          */

         lBytesRead = mmioRead( pInfo->hmmioSS,
                                (CHAR *) lParam1,
                                lParam2 );

         /*
          *  Check the return code and determine if read was successful.
          *  Read must return:
          *    -1 - an error occurred with mmioRead or somewhere internally.
          *     x - number of bytes actually read by mmioRead.
          */

         if ( lBytesRead < 0L )
            {
            return( -1L );
            }
         else
            {
            return( lBytesRead );
            }

         break;

      case MMIOM_WRITE:
         /*
          * Call the write API with the Storage System handle using the
          * parameters that have been passed in to this I/O proc.
          */

         lBytesWritten = mmioWrite( pInfo->hmmioSS,
                                    (CHAR *) lParam1,
                                    lParam2 );

         /*
          *  Check the return code and determine if write was successful.
          *  Write must return:
          *    -1 - an error occurred with mmioWrite or somewhere internally.
          *     x - number of bytes actually written by mmioWrite.
          */

         if ( lBytesWritten < 0L )
            {
            return( -1L );
            }
         else if ( lBytesWritten != lParam2 )
            {
            pmmioinfo->ulErrorRet = MMIOERR_CANNOTWRITE;
            return( lBytesWritten );
            }
         else
            {

            /*
             * Set the Flags field in the CONV header to show it was modified.
             */

            pconvHeaderInfo = (PCONVHEADERINFO)pmmioinfo->pExtraInfoStruct;

            if (pconvHeaderInfo)
               pconvHeaderInfo->ulFlags = CONV_MODIFIED_FILE;

            return( lBytesWritten );
            }

         break;

      case MMIOM_SEEK:
         /*
          * Call the seek API with the Storage System handle using the
          * parameters that have been passed in to this I/O proc.
          */

         lReturnCode = mmioSeek( pInfo->hmmioSS,
                                 lParam1,
                                 lParam2 );

         /*
          *  Check the return code and determine if seek was successful.
          *  Seek must return:
          *    -1 - an error occurred with mmioSeek or somewhere internally.
          *     x - new current file postion from the beginning of the file.
          */

         if ( lReturnCode < 0L )
            {
            return( -1L );
            }

         return( lReturnCode );

         break;

      case MMIOM_CLOSE:
            /*
             * If the CONV header structure was maintained in pExtraInfoStruct,
             * write it back to the beginning of the file.
             */

            if (((pmmioinfo->ulFlags & MMIO_WRITE) ||
                 (pmmioinfo->ulFlags & MMIO_READWRITE)) &&
                 (pmmioinfo->pExtraInfoStruct))

               {
               pconvHeaderInfo = (PCONVHEADERINFO)pmmioinfo->pExtraInfoStruct;

               lReturnCode = mmioSeek( pInfo->hmmioSS,
                                       0L,
                                       SEEK_SET );

               if (lReturnCode < 0L)
                  {
                  return (lReturnCode);
                  }

               ulReturnCode = mmioSetHeader( pmmioinfo->hmmio,
                                             (PVOID)pmmioinfo->pExtraInfoStruct,
                                             sizeof(CONVHEADERINFO),
                                             &lBytesWritten,
                                             0L, 0L );
               if (ulReturnCode)
                  {
                  return (ulReturnCode);
                  }
               }

            if (pmmioinfo->pExtraInfoStruct)
               HhpFreeBuffer((PBYTE)pmmioinfo->pExtraInfoStruct);

            /*
             * Call the close API with the Storage System handle using any
             * parameters that have been passed in to this I/O proc.
             */

            usReturnCode = mmioClose( pInfo->hmmioSS, 0L );
            return ((ULONG)usReturnCode);

         break;

      case MMIOM_IDENTIFYFILE:
         /*
          * Get the filename from parameter. Then create a File Format header
          * in memory since this message use this structure.
          */

         pszFileName = (CHAR *)lParam1;  // get the filename from parameter.

         pconvHeaderInfo =
            (PCONVHEADERINFO)HhpAllocBuffer( sizeof(CONVHEADERINFO), 0);

         if (!pconvHeaderInfo)
            {
            return (MMIO_ERROR);
            }

         hmmioSS = (HMMIO)lParam2;       // get the SS handle to the file.

         if ( !hmmioSS )
            {
            HhpFreeBuffer((PBYTE)pconvHeaderInfo);
            return (MMIO_ERROR);
            }
         else
            {

            /*
             * Seek the file to the beginning to read in the file header.
             */

            lFilePosition = mmioSeek( hmmioSS,
                                      0L,
                                      SEEK_SET );

            if (lFilePosition < 0L)
               {
               HhpFreeBuffer((PBYTE)pconvHeaderInfo);
               return (MMIO_ERROR);
               }

            /*
             * Compare convHeaderInfo.szHeaderText with text string defined
             * in the convproc.h header file.
             */

            lBytesRead = mmioRead( hmmioSS,
                                   (PSZ)pconvHeaderInfo,
                                   sizeof(CONVHEADERINFO) );

            if ( lBytesRead <= 0L )
               {
               HhpFreeBuffer((PBYTE)pconvHeaderInfo);
               return( -1L );
               }

            pTemp = (CHAR *)pconvHeaderInfo;
            pTemp += 2 * sizeof(ULONG);

            if (!strncmp( pTemp, HEADER_STRING, strlen(HEADER_STRING) ))
               {
               HhpFreeBuffer((PBYTE)pconvHeaderInfo);
               return( 0L );
               }
            else
               {
               HhpFreeBuffer((PBYTE)pconvHeaderInfo);
               return( -1L );
               }
            }

         break;

      case MMIOM_GETFORMATINFO:

         /*
          * Fill in the mmformatinfo for the CONVProc.
          */

         pmmformatinfo = (PMMFORMATINFO)lParam1;

         if (pmmformatinfo == NULL)
            {
            return( -1L );
            }

         pmmformatinfo->ulStructLen = sizeof(MMFORMATINFO);
         pmmformatinfo->fccIOProc = FOURCC_FFT;
         pmmformatinfo->ulIOProcType = MMIO_IOPROC_FILEFORMAT;
         pmmformatinfo->ulMediaType = MMIO_MEDIATYPE_OTHER;
         pmmformatinfo->ulFlags = MMIO_CANREADUNTRANSLATED      |
                                  MMIO_CANWRITEUNTRANSLATED     |
                                  MMIO_CANREADWRITEUNTRANSLATED |
                                  MMIO_CANSEEKUNTRANSLATED;

         memset( pmmformatinfo->szDefaultFormatExt,  '\0',
            sizeof(pmmformatinfo->szDefaultFormatExt)  );
         strcpy( pmmformatinfo->szDefaultFormatExt,  "FFT" );

         if (convhlpGetNLSData( &pmmformatinfo->ulCodePage,
                                &pmmformatinfo->ulLanguage ))
            {
            return( -1L );
            }

         if (convhlpGetFormatStringLength( FOURCC_FFT,
                                           &(pmmformatinfo->lNameLength) ))
            {
            return( -1L );
            }

         return( 0L );
         break;

      case MMIOM_GETFORMATNAME:

         /*
          * The string is in a resource file (CONVPROC.RC) for NLS purposes.
          */

         pszFormatString = (CHAR *)lParam1;

         lBytesCopied = convhlpGetFormatString( FOURCC_FFT,
                                                pszFormatString,
                                                lParam2 );

         return( lBytesCopied );
         break;

      case MMIOM_QUERYHEADERLENGTH:

         /*
          * Save current file position for later restore. Then
          * seek the file to the beginning to read in the header.
          */

         lSavedFilePosition = pmmioinfo->lLogicalFilePos;

         lFilePosition = mmioSeek( pInfo->hmmioSS,
                                   0L,
                                   SEEK_SET );

         if (lFilePosition < 0L)
            {
            return (0L);
            }

         /*
          * Read in the header length for the file. It is the first 4 bytes.
          */

         lBytesRead = mmioRead( pInfo->hmmioSS,
                                szHeaderLength,
                                sizeof(ULONG) );

         lReturnCode = mmioSeek( pInfo->hmmioSS,
                                 lSavedFilePosition,
                                 SEEK_SET );

         if (lReturnCode != lSavedFilePosition)
            {
            return (0L);
            }

         if (lBytesRead <= 0L)
            {
            return (0L);
            }
         else
            {
            lHeaderLength = (LONG)(*((LONG *)szHeaderLength));
            return (lHeaderLength);
            }

         break;

      case MMIOM_GETHEADER:

         /*
          * Save current file position for later restore. Then
          * seek the file to the beginning to read in the header.
          */

         lSavedFilePosition = pmmioinfo->lLogicalFilePos;

         lFilePosition = mmioSeek( pInfo->hmmioSS,
                                   0L,
                                   SEEK_SET );

         if (lFilePosition < 0L)
            {
            return (0L);
            }

         /*
          * Read the header of the file into the provided buffer for the
          * given length. Then seek the file back to the saved position.
          */

         lBytesRead = mmioRead( pInfo->hmmioSS,
                                (CHAR *)lParam1,
                                lParam2 );

         lReturnCode = mmioSeek( pInfo->hmmioSS,
                                 lSavedFilePosition,
                                 SEEK_SET );

         if (lReturnCode != lSavedFilePosition)
            {
            return (0L);
            }

         if (lBytesRead <= 0L)
            {
            return (0L);
            }
         else
            {
            return (lBytesRead);
            }

         break;

      case MMIOM_SETHEADER:

         /*
          * Save current file position for later restore. Then
          * seek the file to the beginning to read in the header.
          */

         lSavedFilePosition = pmmioinfo->lLogicalFilePos;

         lFilePosition = mmioSeek( pInfo->hmmioSS,
                                   0L,
                                   SEEK_SET );

         if (lFilePosition < 0L)
            {
            return (0L);
            }

         /*
          * Write the entire header to the file. Then seek the file back
          * to the saved file position.
          */

         lBytesWritten = mmioWrite( pInfo->hmmioSS,
                                    (CHAR *)lParam1,
                                    lParam2 );

         lReturnCode = mmioSeek( pInfo->hmmioSS,
                                 lSavedFilePosition,
                                 SEEK_SET );

         if (lReturnCode != lSavedFilePosition)
            {
            return (0L);
            }

         if (lBytesWritten <= 0L)
            {
            return (0L);
            }
         else
            {
            return (lBytesWritten);
            }

         break;

      case CONVM_TOUPPER:

         pszData = (CHAR *)lParam1;
         convhlpToUpper( (PUCHAR)pszData );
         return (MMIO_SUCCESS);

         break;

      case CONVM_TOLOWER:

         pszData = (CHAR *)lParam1;
         convhlpToLower( (PUCHAR)pszData );
         return (MMIO_SUCCESS);

         break;

      default:

         /*
          * If an IO Proc has a child IO Proc, then instead of
          * returning UNSUPPORTED_MESSAGE, send the message to
          * the child IO Proc to see if it can understand and
          * process the message.
          *
          * Since message is unexpected, need to check for valid
          * pointers.
          */

         if (pInfo)
            {
            if (pInfo->hmmioSS)
               {
               lReturnCode = ( mmioSendMessage( pInfo->hmmioSS,
                                                usMsg,
                                                lParam1,
                                                lParam2 ));
           
               if (!lReturnCode)
                   pmmioinfo->ulErrorRet = mmioGetLastError(pInfo->hmmioSS);
               return (lReturnCode);
               }
            }
          else
            {
            if (pmmioinfo)
                pmmioinfo->ulErrorRet = MMIOERR_UNSUPPORTED_MESSAGE;
            }

          return (MMIOERR_UNSUPPORTED_MESSAGE);

      }

}
예제 #13
0
static int read_word(HMMIO rw, WORD *i)
{
	int rc = mmioRead( rw, (char *)i, sizeof(WORD) );
	IF_ERR(rc != sizeof(WORD), 0);
	return 1;
}
예제 #14
0
static int read_ubyte(HMMIO rw, ubyte *i)
{
	int rc = mmioRead( rw, (char *)i, sizeof(ubyte) );
	IF_ERR(rc != sizeof(ubyte), 0);
	return 1;
}
예제 #15
0
//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;
			ZeroMemory(&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 ){
						FillMemory((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{
					FillMemory((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;
}
예제 #16
0
파일: Sound.cpp 프로젝트: bmer/Alchemy
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;
			}
		}
	}
예제 #17
0
파일: mmio.c 프로젝트: hoangduit/reactos
/**************************************************************************
 * 				mmioDescend         	[WINMM.@]
 */
MMRESULT WINAPI mmioDescend(HMMIO hmmio, LPMMCKINFO lpck,
                            const MMCKINFO* lpckParent, UINT uFlags)
{
    DWORD		dwOldPos;
    FOURCC		srchCkId;
    FOURCC		srchType;

    TRACE("(%p, %p, %p, %04X);\n", hmmio, lpck, lpckParent, uFlags);

    if (lpck == NULL)
	return MMSYSERR_INVALPARAM;

    dwOldPos = mmioSeek(hmmio, 0, SEEK_CUR);
    TRACE("dwOldPos=%d\n", dwOldPos);

    if (lpckParent != NULL) {
	TRACE("seek inside parent at %d !\n", lpckParent->dwDataOffset);
	/* EPP: was dwOldPos = mmioSeek(hmmio,lpckParent->dwDataOffset,SEEK_SET); */
	if (dwOldPos < lpckParent->dwDataOffset ||
	    dwOldPos >= lpckParent->dwDataOffset + lpckParent->cksize) {
	    WARN("outside parent chunk\n");
	    return MMIOERR_CHUNKNOTFOUND;
	}
    }

    /* The SDK docu says 'ckid' is used for all cases. Real World
     * examples disagree -Marcus,990216.
     */

    srchCkId = 0;
    srchType = 0;

    /* find_chunk looks for 'ckid' */
    if (uFlags & MMIO_FINDCHUNK)
	srchCkId = lpck->ckid;

    /* find_riff and find_list look for 'fccType' */
    if (uFlags & MMIO_FINDLIST)
    {
	srchCkId = FOURCC_LIST;
        srchType = lpck->fccType;
    }

    if (uFlags & MMIO_FINDRIFF)
    {
	srchCkId = FOURCC_RIFF;
        srchType = lpck->fccType;
    }

    TRACE("searching for %4.4s.%4.4s\n",
          (LPCSTR)&srchCkId, srchType ? (LPCSTR)&srchType : "any");

    while (TRUE)
    {
        LONG ix;

        ix = mmioRead(hmmio, (LPSTR)lpck, 3 * sizeof(DWORD));
        if (ix < 2*sizeof(DWORD))
        {
            mmioSeek(hmmio, dwOldPos, SEEK_SET);
            WARN("return ChunkNotFound\n");
            return MMIOERR_CHUNKNOTFOUND;
        }

        lpck->dwDataOffset = dwOldPos + 2 * sizeof(DWORD);
        TRACE("ckid=%4.4s fcc=%4.4s cksize=%08X !\n",
              (LPCSTR)&lpck->ckid,
              srchType ? (LPCSTR)&lpck->fccType:"<na>",
              lpck->cksize);
        if ( (!srchCkId || (srchCkId == lpck->ckid)) &&
             (!srchType || (srchType == lpck->fccType)) )
            break;

        dwOldPos = lpck->dwDataOffset + ((lpck->cksize + 1) & ~1);
        mmioSeek(hmmio, dwOldPos, SEEK_SET);
    }

    lpck->dwFlags = 0;
    /* If we were looking for RIFF/LIST chunks, the final file position
     * is after the chunkid. If we were just looking for the chunk
     * it is after the cksize. So add 4 in RIFF/LIST case.
     */
    if (lpck->ckid == FOURCC_RIFF || lpck->ckid == FOURCC_LIST)
	mmioSeek(hmmio, lpck->dwDataOffset + sizeof(DWORD), SEEK_SET);
    else
    {
	mmioSeek(hmmio, lpck->dwDataOffset, SEEK_SET);
	lpck->fccType = 0;
    }
    TRACE("lpck: ckid=%.4s, cksize=%d, dwDataOffset=%d fccType=%08X (%.4s)!\n",
	  (LPSTR)&lpck->ckid, lpck->cksize, lpck->dwDataOffset,
	  lpck->fccType, srchType?(LPSTR)&lpck->fccType:"");
    return MMSYSERR_NOERROR;
}
예제 #18
0
int DSound_Load_WAV(const char *filename, int control_flags)
{
   // this function loads a .wav file, sets up the directsound 
   // buffer and loads the data into memory, the function returns 
   // the id number of the sound

   HMMIO 			hwav;       // handle to wave file
   MMCKINFO		parent,        // parent chunk
                  child;      // child chunk
   WAVEFORMATEX    wfmtx;     // wave format structure

   int	sound_id = -1,       // id of sound to be loaded
	   index;                  // looping variable

   UCHAR *snd_buffer,         // temporary sound buffer to hold voc data
         *audio_ptr_1=NULL,   // data ptr to first write buffer 
	   *audio_ptr_2=NULL;      // data ptr to second write buffer

   DWORD audio_length_1=0,    // length of first write buffer
	   audio_length_2=0;       // length of second write buffer
   			
   // step one: are there any open id's ?
   for (index=0; index < MAX_SOUNDS; index++)
   {
      // make sure this sound is unused
	   if (sound_fx[index].state==SOUND_NULL)
      {
	      sound_id = index;
	      break;
      } 
   }

   // did we get a free id?
   if (sound_id==-1)
	   return(-1);

   // set up chunk info structure
   parent.ckid          = (FOURCC)0;
   parent.cksize        = 0;
   parent.fccType       = (FOURCC)0;
   parent.dwDataOffset  = 0;
   parent.dwFlags       = 0;

   // copy data
   child = parent;

   // open the WAV file
   if ((hwav = mmioOpen((LPSTR)filename, NULL, MMIO_READ | MMIO_ALLOCBUF))==NULL)
      return(-1);

   // descend into the RIFF 
   parent.fccType = mmioFOURCC('W', 'A', 'V', 'E');

   if (mmioDescend(hwav, &parent, NULL, MMIO_FINDRIFF))
   {
      // close the file
      mmioClose(hwav, 0);
      return(-1); 
   } 

   // descend to the WAVEfmt 
   child.ckid = mmioFOURCC('f', 'm', 't', ' ');

   if (mmioDescend(hwav, &child, &parent, 0))
   {
      // close the file
      mmioClose(hwav, 0);
      return(-1); 	
   } 

   // now read the wave format information from file
   if (mmioRead(hwav, (char *)&wfmtx, sizeof(wfmtx)) != sizeof(wfmtx))
   {
      // close file
      mmioClose(hwav, 0);
      return(-1);
   }

   // make sure that the data format is PCM
   if (wfmtx.wFormatTag != WAVE_FORMAT_PCM)
   {
      // close the file
      mmioClose(hwav, 0);
      return(-1); 
   } 

   // now ascend up one level, so we can access data chunk
   if (mmioAscend(hwav, &child, 0))
   {
      // close file
      mmioClose(hwav, 0);
      return(-1); 	
   }
   // descend to the data chunk 
   child.ckid = mmioFOURCC('d', 'a', 't', 'a');

   if (mmioDescend(hwav, &child, &parent, MMIO_FINDCHUNK))
   {
      // close file
      mmioClose(hwav, 0);
      return(-1); 	
   } 

   // finally!!!! now all we have to do is read the data in and
   // set up the directsound buffer

   // allocate the memory to load sound data
   snd_buffer = (UCHAR *)malloc(child.cksize);

   // read the wave data 
   mmioRead(hwav, (char *)snd_buffer, child.cksize);

   // close the file
   mmioClose(hwav, 0);

   // set rate and size in data structure
   sound_fx[sound_id].rate  = wfmtx.nSamplesPerSec;
   sound_fx[sound_id].size  = child.cksize;
   sound_fx[sound_id].state = SOUND_LOADED;

   // set up the format data structure
   memset(&pcmwf, 0, sizeof(WAVEFORMATEX));

   pcmwf.wFormatTag        = WAVE_FORMAT_PCM;  // pulse code modulation
   pcmwf.nChannels         = 1;                // mono 
   pcmwf.nSamplesPerSec    = 11025;            // always this rate
   pcmwf.nBlockAlign       = 1;                
   pcmwf.nAvgBytesPerSec   = pcmwf.nSamplesPerSec * pcmwf.nBlockAlign;
   pcmwf.wBitsPerSample    = 8;
   pcmwf.cbSize            = 0;

   // prepare to create sounds buffer
   dsbd.dwSize			= sizeof(DSBUFFERDESC);
   dsbd.dwFlags		= control_flags | DSBCAPS_STATIC | DSBCAPS_LOCSOFTWARE;
   dsbd.dwBufferBytes	= child.cksize;
   dsbd.lpwfxFormat	= &pcmwf;

   // create the sound buffer
   if (FAILED(lpds->CreateSoundBuffer(&dsbd,&sound_fx[sound_id].dsbuffer,NULL)))
   {
      // release memory
      free(snd_buffer);
      return(-1);
   } 

   // copy data into sound buffer
   if (FAILED(sound_fx[sound_id].dsbuffer->Lock(0,					 
								         child.cksize,			
								         (void **) &audio_ptr_1, 
								         &audio_length_1,
								         (void **)&audio_ptr_2, 
								         &audio_length_2,
								         DSBLOCK_FROMWRITECURSOR)))
								   return(0);

   // copy first section of circular buffer
   memcpy(audio_ptr_1, snd_buffer, audio_length_1);

   // copy last section of circular buffer
   memcpy(audio_ptr_2, (snd_buffer+audio_length_1),audio_length_2);

   // unlock the buffer
   if (FAILED(sound_fx[sound_id].dsbuffer->Unlock(audio_ptr_1, 
									      audio_length_1, 
									      audio_ptr_2, 
									      audio_length_2)))
 							      return(0);

   // release the temp buffer
   free(snd_buffer);
   return(sound_id);
}
예제 #19
0
/* 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);

}
예제 #20
0
//************************************************************************
BOOL CDirSnd::LoadWaveResource(LPSTR lpSound, HINSTANCE hInstance, BOOL b3D)
// lpSound is a resource name
//************************************************************************
{
	HGLOBAL hWave;
	LPTR lpWave;
    PCMWAVEFORMAT pcm; 
	HMMIO hio;
	MMCKINFO RiffChunk;
	MMCKINFO FmtChunk;
	MMCKINFO DataChunk;
	HRESULT hr;
	MMRESULT Res;
	MMIOINFO Info;
	long lRead;

	WAVEFORMATEX Format;
	DSBUFFERDESC BuffDesc;

	BYTE *pData1;
	BYTE *pData2;
	DWORD dwBytes1;
	DWORD dwBytes2;

	Init( GetApp()->GetMainWnd() );

	if ( !m_pDirectSound )
		return NO;

	if ( !hInstance )
		return NO;

	// Find the resource
	if ( !(hWave = (HGLOBAL)FindResource( hInstance, lpSound, "WAVE" )) )
		return NO;

	// Load the resource
	if ( !(hWave = LoadResource( hInstance, (HRSRC)hWave )) )
		return( NO );

	// Lock it
	if ( !(lpWave = (LPTR)LockResource( hWave )) )
	{
		FreeResource( hWave );
		return NO;
	}

	// Set up mmio Info structure for opening memory for mmio
	memset(&Info, 0, sizeof(MMIOINFO));
	Info.pchBuffer = (LPSTR)lpWave;
	Info.fccIOProc = FOURCC_MEM;
	Info.cchBuffer = SizeofResource(hInstance, (HRSRC)hWave);  
	Info.adwInfo[0] = 0;

	// Open memory for mmio
	hio = mmioOpen(NULL, &Info, MMIO_READ); 
	if (!hio)
		return 0;

	// Descened into the WAVE section
	RiffChunk.ckid = FOURCC_RIFF;
	RiffChunk.fccType = mmioFOURCC('W', 'A', 'V', 'E' );
	Res = mmioDescend(hio, &RiffChunk, NULL, MMIO_FINDRIFF);
	if (Res != 0)
		goto ERROR_READING_WAVE;

    // Descend into the fmt chunk
    FmtChunk.ckid = mmioFOURCC('f', 'm', 't', ' ');
    Res = mmioDescend(hio, &FmtChunk, &RiffChunk, MMIO_FINDCHUNK);
	if (Res != 0)
		goto ERROR_READING_WAVE;
                                                                                                                                                               
	// Read the 'fmt ' chunk into <pcmWaveFormat>
    if (mmioRead(hio, (HPSTR) &pcm, (long)sizeof(pcm)) 
		!= (long) sizeof(pcm))
	    goto ERROR_READING_WAVE;
                                                                                                           

	DataChunk.ckid = mmioFOURCC('d', 'a', 't', 'a');
	Res = mmioDescend(hio, &DataChunk, &RiffChunk, MMIO_FINDCHUNK);
	if (Res != 0)
		goto ERROR_READING_WAVE;

	// Set the wave format 
	memset(&Format, 0, sizeof(WAVEFORMATEX));
	Format.wFormatTag = pcm.wf.wFormatTag;
	Format.nChannels = pcm.wf.nChannels;
	Format.nSamplesPerSec = pcm.wf.nSamplesPerSec;
	Format.nAvgBytesPerSec = pcm.wf.nAvgBytesPerSec;
	Format.nBlockAlign = pcm.wf.nBlockAlign;
	Format.wBitsPerSample = pcm.wBitsPerSample;

	// Set up the sound buffer description
	memset(&BuffDesc, 0, sizeof(BuffDesc));
	BuffDesc.dwSize = sizeof(DSBUFFERDESC);
	if (b3D)
		BuffDesc.dwFlags = DSBCAPS_CTRLVOLUME|DSBCAPS_CTRL3D;
	else
		BuffDesc.dwFlags = DSBCAPS_CTRLDEFAULT;
	BuffDesc.dwBufferBytes = DataChunk.cksize;
	BuffDesc.lpwfxFormat = &Format;


	// Create the buffer
    hr =  m_pDirectSound->CreateSoundBuffer( &BuffDesc, &m_pBuffer, NULL);

	if (hr != DS_OK)
	{
		goto ERROR_READING_WAVE;
	}

	if (b3D)
	{
		hr = m_pBuffer->QueryInterface(IID_IDirectSound3DBuffer, (void **)&m_p3dBuff);
		//hr = m_pBuffer->QueryInterface(IID_IMAPISession, (void **)&m_p3dBuff);
		if (SUCCEEDED(hr)) 
		{
			// Set 3D parameters of this sound.
			hr = m_p3dBuff->SetPosition(D3DVAL(0), D3DVAL(0), D3DVAL(0), DS3D_IMMEDIATE);
		}
	}

	// Lock the buffer so we can read into it
	hr = m_pBuffer->Lock(0, DataChunk.cksize, &pData1, &dwBytes1, 
		&pData2, &dwBytes2, 0);
    
    // If we got DSERR_BUFFERLOST, restore and retry lock.
    if (DSERR_BUFFERLOST == hr)
	{
        m_pBuffer->Restore();
		hr = m_pBuffer->Lock(0, DataChunk.cksize, &pData1, &dwBytes1, 
			&pData2, &dwBytes2, 0);
    }

	// Read the data
	lRead = mmioRead(hio, (HPSTR)pData1, dwBytes1);
	if (pData2 != NULL)
		lRead = mmioRead(hio, (HPSTR)pData2, dwBytes2);

    // Release the data back to DirectSound.
    hr = m_pBuffer->Unlock(pData1, dwBytes1, pData2, dwBytes2);

	ERROR_READING_WAVE:

	mmioClose(hio, 0);	
	
	return YES;
}
예제 #21
0
파일: mmoutput.c 프로젝트: iamfil/wine
BOOL MCIAVI_GetInfo(WINE_MCIAVI* wma)
{
    MMCKINFO		ckMainRIFF;
    MMCKINFO		mmckHead;
    MMCKINFO		mmckList;
    MMCKINFO		mmckInfo;
    AVIStreamHeader strh;
    struct AviListBuild alb;
    DWORD stream_n;

    if (mmioDescend(wma->hFile, &ckMainRIFF, NULL, 0) != 0) {
	WARN("Can't find 'RIFF' chunk\n");
	return FALSE;
    }

    if ((ckMainRIFF.ckid != FOURCC_RIFF) || (ckMainRIFF.fccType != formtypeAVI)) {
	WARN("Can't find 'AVI ' chunk\n");
	return FALSE;
    }

    mmckHead.fccType = listtypeAVIHEADER;
    if (mmioDescend(wma->hFile, &mmckHead, &ckMainRIFF, MMIO_FINDLIST) != 0) {
	WARN("Can't find 'hdrl' list\n");
	return FALSE;
    }

    mmckInfo.ckid = ckidAVIMAINHDR;
    if (mmioDescend(wma->hFile, &mmckInfo, &mmckHead, MMIO_FINDCHUNK) != 0) {
	WARN("Can't find 'avih' chunk\n");
	return FALSE;
    }

    mmioRead(wma->hFile, (LPSTR)&wma->mah, sizeof(wma->mah));

    TRACE("mah.dwMicroSecPerFrame=%d\n", 	wma->mah.dwMicroSecPerFrame);
    TRACE("mah.dwMaxBytesPerSec=%d\n", 	wma->mah.dwMaxBytesPerSec);
    TRACE("mah.dwPaddingGranularity=%d\n", 	wma->mah.dwPaddingGranularity);
    TRACE("mah.dwFlags=%d\n", 			wma->mah.dwFlags);
    TRACE("mah.dwTotalFrames=%d\n", 		wma->mah.dwTotalFrames);
    TRACE("mah.dwInitialFrames=%d\n", 		wma->mah.dwInitialFrames);
    TRACE("mah.dwStreams=%d\n", 		wma->mah.dwStreams);
    TRACE("mah.dwSuggestedBufferSize=%d\n",	wma->mah.dwSuggestedBufferSize);
    TRACE("mah.dwWidth=%d\n", 			wma->mah.dwWidth);
    TRACE("mah.dwHeight=%d\n", 		wma->mah.dwHeight);

    mmioAscend(wma->hFile, &mmckInfo, 0);

    TRACE("Start of streams\n");
    wma->video_stream_n = 0;
    wma->audio_stream_n = 0;

    for (stream_n = 0; stream_n < wma->mah.dwStreams; stream_n++)
    {
        MMCKINFO mmckStream;

        mmckList.fccType = listtypeSTREAMHEADER;
        if (mmioDescend(wma->hFile, &mmckList, &mmckHead, MMIO_FINDLIST) != 0)
            break;

        mmckStream.ckid = ckidSTREAMHEADER;
        if (mmioDescend(wma->hFile, &mmckStream, &mmckList, MMIO_FINDCHUNK) != 0)
        {
            WARN("Can't find 'strh' chunk\n");
            continue;
        }

        mmioRead(wma->hFile, (LPSTR)&strh, sizeof(strh));

        TRACE("Stream #%d fccType %4.4s\n", stream_n, (LPSTR)&strh.fccType);

        if (strh.fccType == streamtypeVIDEO)
        {
            TRACE("found video stream\n");
            if (wma->inbih)
                WARN("ignoring another video stream\n");
            else
            {
                wma->ash_audio = strh;

                if (!MCIAVI_GetInfoVideo(wma, &mmckList, &mmckStream))
                    return FALSE;
                wma->video_stream_n = stream_n;
            }
        }
        else if (strh.fccType == streamtypeAUDIO)
        {
            TRACE("found audio stream\n");
            if (wma->lpWaveFormat)
                WARN("ignoring another audio stream\n");
            else
            {
                wma->ash_video = strh;

                if (!MCIAVI_GetInfoAudio(wma, &mmckList, &mmckStream))
                    return FALSE;
                wma->audio_stream_n = stream_n;
            }
        }
        else
            TRACE("Unsupported stream type %4.4s\n", (LPSTR)&strh.fccType);

        mmioAscend(wma->hFile, &mmckList, 0);
    }

    TRACE("End of streams\n");

    mmioAscend(wma->hFile, &mmckHead, 0);

    /* no need to read optional JUNK chunk */

    mmckList.fccType = listtypeAVIMOVIE;
    if (mmioDescend(wma->hFile, &mmckList, &ckMainRIFF, MMIO_FINDLIST) != 0) {
	WARN("Can't find 'movi' list\n");
	return FALSE;
    }

    wma->dwPlayableVideoFrames = wma->mah.dwTotalFrames;
    wma->lpVideoIndex = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
				  wma->dwPlayableVideoFrames * sizeof(struct MMIOPos));
    if (!wma->lpVideoIndex) {
	WARN("Can't alloc video index array\n");
	return FALSE;
    }
    wma->dwPlayableAudioBlocks = 0;
    wma->lpAudioIndex = NULL;

    alb.numAudioBlocks = alb.numVideoFrames = 0;
    alb.inVideoSize = alb.inAudioSize = 0;
    alb.numAudioAllocated = 0;

    while (mmioDescend(wma->hFile, &mmckInfo, &mmckList, 0) == 0) {
	if (mmckInfo.fccType == listtypeAVIRECORD) {
	    MMCKINFO	tmp;

	    while (mmioDescend(wma->hFile, &tmp, &mmckInfo, 0) == 0) {
		MCIAVI_AddFrame(wma, &tmp, &alb);
		mmioAscend(wma->hFile, &tmp, 0);
	    }
	} else {
	    MCIAVI_AddFrame(wma, &mmckInfo, &alb);
	}

	mmioAscend(wma->hFile, &mmckInfo, 0);
    }
    if (alb.numVideoFrames != wma->dwPlayableVideoFrames) {
	WARN("Found %d video frames (/%d), reducing playable frames\n",
	     alb.numVideoFrames, wma->dwPlayableVideoFrames);
	wma->dwPlayableVideoFrames = alb.numVideoFrames;
    }
    wma->dwPlayableAudioBlocks = alb.numAudioBlocks;

    if (alb.inVideoSize > wma->ash_video.dwSuggestedBufferSize) {
	WARN("inVideoSize=%d suggestedSize=%d\n", alb.inVideoSize, wma->ash_video.dwSuggestedBufferSize);
	wma->ash_video.dwSuggestedBufferSize = alb.inVideoSize;
    }
    if (alb.inAudioSize > wma->ash_audio.dwSuggestedBufferSize) {
	WARN("inAudioSize=%d suggestedSize=%d\n", alb.inAudioSize, wma->ash_audio.dwSuggestedBufferSize);
	wma->ash_audio.dwSuggestedBufferSize = alb.inAudioSize;
    }

    wma->indata = HeapAlloc(GetProcessHeap(), 0, wma->ash_video.dwSuggestedBufferSize);
    if (!wma->indata) {
	WARN("Can't alloc input buffer\n");
	return FALSE;
    }

    return TRUE;
}
예제 #22
0
	/** MMIOストリームから読み込み
	 *
	 * @author SAM (T&GG, Org.)<*****@*****.**>
	 * @date 2004/01/21 2:36:59
	 * Copyright (C) 2001,2002,2003,2004 SAM (T&GG, Org.). All rights reserved.
	 */
	HRslt WavFile::readMMIO() {
		MMCKINFO        ckin;           // chunk info. for general use.
		PCMWAVEFORMAT   pcmWaveFormat;  // Temp PCM structure to load in.

		wfx_ = NULL;

		if(mmioDescend(hmmio_, &ckriff_, NULL, 0)) return DXTRACE_ERR(TEXT("mmioDescend"), E_FAIL);

		// Check to make sure this is a valid wave file
		if( (ckriff_.ckid != FOURCC_RIFF) || (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(mmioDescend(hmmio_, &ckin, &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 < sizeof(PCMWAVEFORMAT))
			return DXTRACE_ERR( TEXT("sizeof(PCMWAVEFORMAT)"), E_FAIL );

		// Read the 'fmt ' chunk into <pcmWaveFormat>.
		if( mmioRead( 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 ) {
			wfx_ = reinterpret_cast<WAVEFORMATEX *>(malloc( sizeof(WAVEFORMATEX) ));
			if(!wfx_) return DXTRACE_ERR( TEXT("wfx_"), E_OUTOFMEMORY );

			// Copy the bytes from the pcm structure to the waveformatex structure
			memcpy( wfx_, &pcmWaveFormat, sizeof(pcmWaveFormat) );
			wfx_->cbSize = 0;
		}
		else {
			// Read in length of extra bytes.
			WORD cbExtraBytes = 0L;
			if( mmioRead( hmmio_, (CHAR*)&cbExtraBytes, sizeof(WORD)) != sizeof(WORD) )
				return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL );

			wfx_ = reinterpret_cast<WAVEFORMATEX *>(malloc( sizeof(WAVEFORMATEX) + cbExtraBytes ));
			if(!wfx_) return DXTRACE_ERR( TEXT("new"), E_OUTOFMEMORY );

			// Copy the bytes from the pcm structure to the waveformatex structure
			memcpy( wfx_, &pcmWaveFormat, sizeof(pcmWaveFormat) );
			wfx_->cbSize = cbExtraBytes;

			// Now, read those extra bytes into the structure, if cbExtraAlloc != 0.
			if( mmioRead( hmmio_, (CHAR*)(((BYTE*)&(wfx_->cbSize))+sizeof(WORD)), cbExtraBytes ) != cbExtraBytes ) {
				SAFE_FREE( wfx_ );
				return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL );
			}
		}

		// Ascend the input file out of the 'fmt ' chunk.
		if( 0 != mmioAscend( hmmio_, &ckin, 0 ) ) {
			SAFE_FREE( wfx_ );
			return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL );
		}

		return S_OK;
	}
예제 #23
0
파일: animate.c 프로젝트: AmesianX/RosWine
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;
}
예제 #24
0
BOOL CWaveFile::PrepareWaveFile(LPCTSTR lpszFileName)
{
	if(lpszFileName == NULL || *lpszFileName == _T('\0'))
	{
		_stprintf(m_szErrorMsg, _T("Empty file name"));
		return FALSE;
	}

	//The previous opened file is not closed yet
	if(m_hWaveFile != NULL)
	{
		_stprintf(m_szErrorMsg, _T("The previous open file [%s] is not closed yet"), m_szFileName);
		return FALSE;
	}

	_tcscpy(m_szFileName, lpszFileName);

	//Open wave file
	m_hWaveFile = mmioOpen(m_szFileName, NULL, MMIO_READ | MMIO_ALLOCBUF);
	if(m_hWaveFile == NULL)
	{
		_stprintf(m_szErrorMsg, _T("mmioOpen file %s failed"), m_szFileName);
		return FALSE;
	}

	//Chunk info structures
	MMCKINFO ckInfoParent, ckInfo;
	MMRESULT mmResult = 0;

	char* fmtBuffer = NULL;
	LONG lVar;
	BOOL bRet = FALSE;

	do
	{
		//Find riff wave
		ckInfoParent.fccType = mmioFOURCC('W', 'A', 'V', 'E');
		mmResult = mmioDescend(m_hWaveFile, &ckInfoParent, NULL, MMIO_FINDRIFF);
		if(mmResult != MMSYSERR_NOERROR)
		{
			_stprintf(m_szErrorMsg, _T("mmioDescend find riff wave failed"));
			break;
		}

		//Find chunk "fmt "
		ckInfo.ckid = mmioFOURCC('f', 'm', 't', ' ');
		mmResult = mmioDescend(m_hWaveFile, &ckInfo, &ckInfoParent, MMIO_FINDCHUNK);
		if(mmResult != MMSYSERR_NOERROR)
		{
			_stprintf(m_szErrorMsg, _T("mmioDescend find chunk 'fmt ' failed"));
			break;
		}

		//create 'fmt ' buffer
		fmtBuffer = new char[ckInfo.cksize];

		//Read 'fmt ' content
		lVar = mmioRead(m_hWaveFile, (HPSTR)fmtBuffer, ckInfo.cksize);
		if( (DWORD)lVar != ckInfo.cksize )
		{
			_stprintf(m_szErrorMsg, _T("mmioRead read 'fmt ' content failed. fmtSize=%d, read=%d"), 
				ckInfo.cksize, lVar);
			break;
		}
		//remember the fmt
		m_lpWaveFormat = (WAVEFORMATEX*)fmtBuffer;
		m_dwWaveFormatSize = ckInfo.cksize;
		
		//leave chunk 'fmt '
		mmResult = mmioAscend(m_hWaveFile, &ckInfo, 0);
		if(mmResult != MMSYSERR_NOERROR)
		{
			_stprintf(m_szErrorMsg, _T("mmioAscend leave 'fmt ' chunk failed. mmResult=%u"), mmResult);
			break;
		}
		
		//Find chunk 'data'
		ckInfo.ckid = mmioFOURCC('d', 'a', 't', 'a');
		mmResult = mmioDescend(m_hWaveFile, &ckInfo, &ckInfoParent, MMIO_FINDCHUNK);
		if(mmResult != MMSYSERR_NOERROR)
		{
			_stprintf(m_szErrorMsg, _T("mmioDescend find 'data' chunk failed. mmResult=%u"), mmResult);
			break;
		}
		//remember the data chunk info
		m_ckInfoData = ckInfo;
		m_dwDataReadCount = 0;
		
		//Seek the file position to the chunk 'data' start
		lVar = mmioSeek(m_hWaveFile, m_ckInfoData.dwDataOffset, SEEK_SET);
		if((DWORD)lVar != m_ckInfoData.dwDataOffset)
		{
			_stprintf(m_szErrorMsg, _T("mmioSeek to chunk 'data' failed. position=%d"), lVar);
			break;
		}
		
		//everything is ok
		bRet = TRUE;

	} while (FALSE);
	
	if(!bRet)
	{
		if(fmtBuffer != NULL)
		{
			delete[] fmtBuffer;
			fmtBuffer = NULL;
		}
		m_lpWaveFormat = NULL;
	}

	return bRet;
}
예제 #25
0
/**************************************************************************
 * 				mmioRead	       	[MMSYSTEM.1212]
 */
LONG WINAPI mmioRead16(HMMIO16 hmmio, HPSTR pch, LONG cch)
{
    return mmioRead(HMMIO_32(hmmio), pch, cch);
}
예제 #26
0
// Open
BOOL WaveFile::Open (LPSTR pszFilename)
{
    WORD cbExtra = 0;
    DOUT ("WaveFile::Open\n\r");

    BOOL fRtn = SUCCESS;    // assume success
    
    // Open the requested file
    if ((m_hmmio = mmioOpen (pszFilename, NULL, MMIO_ALLOCBUF | MMIO_READ)) == NULL)
    {
        m_mmr = MMIOERR_CANNOTOPEN;
        goto OPEN_ERROR;
    }

    // Descend into initial chunk ('RIFF')
    if (m_mmr = mmioDescend (m_hmmio, &m_mmckiRiff, NULL, 0))
    {
        goto OPEN_ERROR;
    }
    
    // Validate that it's a WAVE file
    if ((m_mmckiRiff.ckid != FOURCC_RIFF) || (m_mmckiRiff.fccType != mmioFOURCC('W', 'A', 'V', 'E')))
    {
        m_mmr = MMIOERR_INVALIDFILE;
        goto OPEN_ERROR;
    }
    
    // Find format chunk ('fmt '), allocate and fill WAVEFORMATEX structure
    m_mmckiFmt.ckid = mmioFOURCC('f', 'm', 't', ' ');
    if (m_mmr = mmioDescend (m_hmmio, &m_mmckiFmt, &m_mmckiRiff, MMIO_FINDCHUNK))
    {
        goto OPEN_ERROR;
    }
    
    // Read the format chunk into temporary structure
    PCMWAVEFORMAT pcmwf;
    if (mmioRead (m_hmmio, (CHAR *) &pcmwf, sizeof(PCMWAVEFORMAT)) != sizeof(PCMWAVEFORMAT))
    {
        m_mmr = MMIOERR_CANNOTREAD;
        goto OPEN_ERROR;
    }

    // If format is not PCM, then there are extra bytes appended to WAVEFORMATEX
    if (pcmwf.wf.wFormatTag != WAVE_FORMAT_PCM)
    {
        // Read WORD specifying number of extra bytes
        if (mmioRead (m_hmmio, (LPSTR) &cbExtra, sizeof (cbExtra)) != sizeof(cbExtra))
        {
            m_mmr = MMIOERR_CANNOTREAD;
            goto OPEN_ERROR;
        }
    }

    // Allocate memory for WAVEFORMATEX structure + extra bytes
    // UNDONE: GMEM_FIXED???? use malloc?
    if (m_pwfmt = (WAVEFORMATEX *) GlobalAlloc (GMEM_FIXED, sizeof(WAVEFORMATEX)+cbExtra))
    {
        // Copy bytes from temporary format structure
        memcpy (m_pwfmt, &pcmwf, sizeof(pcmwf));
        m_pwfmt->cbSize = cbExtra;
        
        // Read those extra bytes, append to WAVEFORMATEX structure
        if (cbExtra != 0)
        {
            if ((m_mmr = mmioRead (m_hmmio, (LPSTR) ((BYTE *)(m_pwfmt) + sizeof (WAVEFORMATEX)), cbExtra)) != cbExtra)
            {
                // Error reading extra bytes
                m_mmr = MMIOERR_CANNOTREAD;
                goto OPEN_ERROR;
            }
        }
    }
    else
    {
        // Error allocating memory
        m_mmr = MMIOERR_OUTOFMEMORY;
        goto OPEN_ERROR;
    }
    
            
    // Init some member data from format chunk
    m_nBlockAlign = m_pwfmt->nBlockAlign;
    m_nAvgDataRate = m_pwfmt->nAvgBytesPerSec;

    // Ascend out of format chunk
    if (m_mmr = mmioAscend (m_hmmio, &m_mmckiFmt, 0))
    {
        goto OPEN_ERROR;
    }

    // Cue for streaming
    Cue ();
    
    // Init some member data from data chunk
    // Note cast to __int64 to prevent rollover error in calculation
    m_nDataSize = m_mmckiData.cksize;
    m_nDuration = (UINT)(((__int64) m_nDataSize * 1000) / m_nAvgDataRate);

    // Successful open!
    goto OPEN_DONE;
    
OPEN_ERROR:
    // Handle all errors here
    fRtn = FALSE;
    if (m_hmmio)
    {
        // Close file
        mmioClose (m_hmmio, 0);
        m_hmmio = NULL;
    }
    if (m_pwfmt)
    {
        // UNDONE: Change here if using malloc
        // Free memory
        GlobalFree (m_pwfmt);
        m_pwfmt = NULL;
    }

OPEN_DONE:
    return (fRtn);
}
예제 #27
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);
}
예제 #28
0
int main(int argc, char *argv[])
{

    //
    // initial seconds count, set to zero.
    
    int seconds = 0;

    //
    // Here we say who we are...
    cout << "WavMix Version 1.1 built " << __DATE__ << "  " << __TIME__ << endl;
    cout << "Application mixes 44.1khz stereo wav files only." << endl;
    cout << endl;

    if (argc < 5)
    {
        //
        //
        cout << endl;
        cout << "     Usage:" << endl;
        cout << "     Provide two source filenames, a target file name, the number of seconds" << endl;
        cout << "     you wish to mix, optional flag to just produce a sample mix, " << endl;
        cout << "     This program REQUIRES MMPM/2 to be installed." << endl;
        cout << endl;
        cout << " This application mixes 44.1khz stereo wav files only.  It will mix two" << endl;
        cout << " source wav files and create a target wav file.  You set the amount of " << endl;
        cout << " overlap in seconds.  WavMix will mix using the seconds of overlap.  A " << endl;
        cout << " preview mode is provided.  Since wave files of this type are extremely " << endl;
        cout << " large, it will produce  a target wav file of just the overlap so you " << endl;
        cout << " may preview your mixdowns" << endl;
        cout << endl;
        cout << endl;
        cout << " Sample command line" << endl;
        cout << " [r:\\audio\\mixdown] wavmix track01.wav track02.wav output.wav 5 " << endl;
        cout << "      Above line mixes track01.wav and track02.wav using 5 seconds " << endl;
        cout << "      of overlap creating output.wav" << endl;
        cout << endl;
        cout << " [r:\\audio\\mixdown] wavmix track01.wav track02.wav output.wav 5 S" << endl;
        cout << "      Above line mixes 5 seconds of audio from the end of track01.wav and the" << endl;
        cout << "      start of track02.wav creating output.wav" << endl;
        
        cout << endl;
        cout << endl;
        cout << "     Support questions or comments to [email protected]" << endl;
            
            
        cout << "Provide filename1 filename2 destinationfile secondtomix (Longcut)" << endl;
        return 1;
    }

    //
    // set the type of mix we are going to do.  if this is true, we do a full mix, if its
    // false, we only will do a "sample" of the mix part.
   short longcut = TRUE;

   if (argc > 5)
   {
       if (strcmp(argv[5],"S")==0)
       {
           cout << "Output file will only be the overlap." << endl;
           longcut = FALSE;
       }
   }
       
   
   seconds= atoi(argv[4]);

   if (seconds == 0)
   {
       cout << " ERROR:  You cannot set seconds-to-mix to 0. " << endl;
       return 5;
   }

  
   MMAUDIOHEADER mmAudioHeader,mmAudioHeader2;
    
    //
    // open file1
   HMMIO hmmio = mmioOpen(argv[1],NULL,MMIO_READ | MMIO_ALLOCBUF);
   if (hmmio==0)
   {
       cout << "Failed to open file " << argv[1] << endl;
       return 1;
   }

   long BytesRead;
   int rc = mmioGetHeader(hmmio,(PVOID)&mmAudioHeader,sizeof(MMAUDIOHEADER),&BytesRead,NULL,NULL);
   if (rc)
   {
       cout << "Error on mmioGetHeader for file " << argv[1] <<  endl;
   }

   //
   // now open the second file

   HMMIO hmmio2 = mmioOpen(argv[2],NULL,MMIO_READ | MMIO_ALLOCBUF);
   if (hmmio2==0)
   {
       cout << "ERROR: Failed to open file " << argv[2] << endl;
       return 2;
   }
   
   rc = mmioGetHeader(hmmio2,(PVOID)&mmAudioHeader2,sizeof(MMAUDIOHEADER),&BytesRead,NULL,NULL);
   if (rc)
   {
       cout << "ERROR on mmioGetHeader 2 " << endl;
       return 3;
   }
   
   //
   // now we are going to create another wave file

   MMIOINFO mmioinfo;

   memset(&mmioinfo,'\0',sizeof(mmioinfo));

   mmioinfo.ulTranslate = MMIO_TRANSLATEHEADER+MMIO_TRANSLATEDATA;
   mmioinfo.aulInfo[3] = MMIO_MEDIATYPE_AUDIO;
   mmioinfo.fccIOProc = mmioFOURCC('W','A','V','E');
   HMMIO hmmioTo = mmioOpen(argv[3],&mmioinfo,MMIO_CREATE+MMIO_WRITE);
 
   if (!hmmioTo)
   {
       cout << "ERROR : Could not create file." << argv[3] <<  endl;
       return 1;
   }


   // here we calculate the OFFSET from the back of the file for the 5 second overlay
   long audiosize = 176400 * seconds; // seconds of audio
   long filesize1 = mmAudioHeader.mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes;
   long filesize2 = mmAudioHeader2.mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes;
   if (audiosize > filesize1)
   {
       cout << "ERROR, you cannot have a mix area that is larger than your source audio file. " << endl;
       return 1;
   }

   if (longcut != TRUE)
   {
       //
       // install the new file size in the buffer
       mmAudioHeader.mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes = audiosize;
       cout << "Total resulting file size is: " << audiosize << endl;
   }

   if (longcut == TRUE)
   {
       //
       // install the new file size in the buffer
       mmAudioHeader.mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes = filesize1 + filesize2;
       cout << "Total resulting file size is: " << (filesize1 + filesize2) << endl;
   }
  
  
   //
   // here we calculate the seekto, not necessary really with longcut
   long seekto = filesize1 - audiosize;

   cout << "Attempting to mix " << seconds << " seconds " << endl;

   //
   // first we copy the begining of file 1 to destfile
   if (longcut==TRUE)
   {
       cout << "Copying " << seekto << " bytes" << endl;
       copyaudio(hmmio,hmmioTo,seekto);
   }
   
   
   //
   // now seek to the new location in file 1
   LONG newPos = mmioSeek(hmmio,seekto,0);
   assert(newPos == seekto);

   //
   // allocate a buffer
   PSHORT pAudio = NULL;
   DosAllocMem((void **) &pAudio,audiosize,PAG_WRITE | PAG_COMMIT);

   //
   // now read the FIRST file
   BytesRead = mmioRead(hmmio,(PCHAR)pAudio,audiosize);
   assert(BytesRead == audiosize);

   //
   // now allocate the second buffer

   PSHORT pAudio2 = NULL;
   DosAllocMem((void **) &pAudio2,audiosize,PAG_WRITE | PAG_COMMIT);

   //
   // and read that in
   BytesRead = mmioRead(hmmio2,(PCHAR)pAudio2,audiosize);
   assert(BytesRead == audiosize);

   //
   // now ADD them together?
   long shortsize = audiosize/2;
   for (unsigned long index = 0; index < shortsize ; index++)
   {
       short part1 = *(pAudio+index);
       short part2 = *(pAudio2+index);
       short result = part1 + part2;
       *(pAudio+index) = result;
           //       *(pAudio+index) = *(pAudio2+index) + *(pAudio+index);
   }

 
   //
   // build the header
   rc = mmioSetHeader(hmmioTo,&mmAudioHeader,sizeof(MMAUDIOHEADER),&BytesRead,0,0);
   if (rc)
   {
       cout << "Error in mmioSetHeader" << endl;
       return 1;
   }

   //
   // write the new file
   rc = mmioWrite(hmmioTo,(PCHAR)pAudio,audiosize);
   if (rc < 0)
   {
       cout << "ERROR during a write" << endl;
   }

   //
   // now, copy the rest of file 2
   if (longcut == TRUE)
   {
       cout << "Copying " << filesize2 - audiosize << " bytes" << endl;
       copyaudio(hmmio2,hmmioTo,filesize2 - audiosize);
   }
   DosFreeMem(pAudio);
   DosFreeMem(pAudio2);
   mmioClose(hmmio,0);
   mmioClose(hmmio2,0);
   mmioClose(hmmioTo,0);

   cout << "Finished, output file created" << endl;
    
    
}
예제 #29
0
TDDSDGenWave::TDDSDGenWave( TDDSD* OWner, const wstring& fname, bool is3D, bool useFX )
{
	FIsStream = false;
	FOwner = OWner;
	FUseFX = useFX;

	//サウンドカードが無いなら、何もしない
	if( ! FOwner->Initialized() )
		return;

	HMMIO hm  =  mmioOpen((LPWSTR)fname.c_str(), NULL, MMIO_READ | MMIO_ALLOCBUF);

	if( hm == 0 ) {
		//PutDebugMessage(fname + 'が、見つかりません');
		return;
	}

	//WAVEに入る
	MMCKINFO mckP;    //親チャンクの情報
	mckP.fccType = MakeFourCC('W','A','V','E');
	if( (mmioDescend(hm, &mckP, NULL, MMIO_FINDRIFF)) != 0 ) {
		mmioClose(hm, 0);
		//PutDebugMessage(fname + 'は、WAVEファイルではありません');
		return;
	}

	//fmtチャンクに入る
	MMCKINFO mckC;    //子チャンクの情報
	mckC.ckid = MakeFourCC('f','m','t',' ');
	if( mmioDescend(hm, &mckC, &mckP, MMIO_FINDCHUNK) != 0 ) {
		mmioClose(hm, 0);
		//PutDebugMessage(fname + 'には、fmtチャンクが有りません');
		return;
	}

	//fmtチャンクを読み取る
	u32 fmtSize  =  mckC.cksize;
	if( mmioRead(hm, (HPSTR)&FWaveFormat, fmtSize) != fmtSize ) {
		mmioClose(hm, 0);
		//PutDebugMessage(fname + 'のfmtチャンクが不正です');
		return;
	}

	//fmtチャンクを抜け、dataチャンクに入る
	mmioAscend(hm, &mckC, 0);
	mckC.ckid = MakeFourCC('d','a','t','a');
	if( mmioDescend(hm, &mckC, &mckP, MMIO_FINDCHUNK) != 0 ) {
		mmioClose(hm, 0);
		//PutDebugMessage(fname + 'には、dataチャンクが有りません');
		return;
	}

	u32 dataSize = mckC.cksize;

	//二次バッファの作成
	DSBUFFERDESC dsbd;
	ZeroMemory(&dsbd, sizeof(dsbd));
	dsbd.dwSize = sizeof(dsbd);
	if( is3D )
		dsbd.dwFlags = DSBCAPS_CTRLVOLUME + DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRL3D;
	else
		dsbd.dwFlags = DSBCAPS_CTRLPAN + DSBCAPS_CTRLVOLUME + DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLPAN;

	if( FUseFX )
		dsbd.dwFlags = DSBCAPS_CTRLPAN + DSBCAPS_CTRLVOLUME + DSBCAPS_CTRLFREQUENCY + DSBCAPS_CTRLFX;


	if( FOwner->FStickyFocus )
		dsbd.dwFlags = dsbd.dwFlags | DSBCAPS_STICKYFOCUS;

	dsbd.dwBufferBytes = dataSize;
	dsbd.lpwfxFormat = &FWaveFormat;

	FLength = dataSize;

	IDirectSoundBuffer* dsb;
	FOwner->DSound()->CreateSoundBuffer(&dsbd, &dsb, NULL);
	dsb->QueryInterface(IID_IDirectSoundBuffer8, (LPVOID*)&FSoundBuffer);
	dsb->Release(); 


	//二次バッファのロック
	LPVOID lpBuf1, lpBuf2;
	DWORD dwBuf1, dwBuf2;
	FSoundBuffer->Lock(0,dataSize, &lpBuf1, &dwBuf1, &lpBuf2, &dwBuf2, 0);

	//音データのロード(dataチャンクを読み取る)
	mmioRead(hm, (HPSTR)lpBuf1, dwBuf1);
	if( dwBuf2 != 0 ) {
		mmioRead(hm, (HPSTR)lpBuf2, dwBuf2);
	}

	FSoundBuffer->Unlock(lpBuf1,dwBuf1,lpBuf2,dwBuf2);
	FSoundBuffer->SetFrequency(FWaveFormat.nSamplesPerSec);
	mmioClose(hm, 0);


}
예제 #30
0
size_t ogg_mmio_read(void* buf, size_t elsize, size_t elnem, void* mmfp)
{
    STRHDL* hdl = (STRHDL*)mmfp;

    return mmioRead(hdl->cfp, (HPSTR)buf, elsize * elnem);
}