UINT CMP3ToWavDlg::ConvertFunc(PVOID pParams) { CUString strLang; int nPeakValue = 0; DWORD dwIndex = 0; CDEX_ERR bErr = CDEX_OK; PBYTE pStream = NULL; DWORD dwTotalTime = 0; ENTRY_TRACE( _T( "ConvertFunc" ) ); CMP3ToWavDlg* pDlg = (CMP3ToWavDlg*)pParams; pDlg->m_wCurrentTrack = 0; pDlg->m_bAbortThread = FALSE; CUString strOutDir(g_config.GetCnvOutputDir()); while( pDlg->m_wCurrentTrack < pDlg->m_nTotalFiles && !pDlg->m_bAbortThread ) { BOOL bNoToAll = FALSE; nPeakValue = 0; POSITION nFileListPos = pDlg->m_Pos; pDlg->m_strMP3FileName = pDlg->m_pFileDlg->GetNextPathName( pDlg->m_Pos ); pDlg->m_strWavFileName = pDlg->m_pFileDlg->GetFileName( nFileListPos ); CUString strSubPath = pDlg->m_pFileDlg->GetSubPath( nFileListPos ); int nPos = pDlg->m_strWavFileName.ReverseFind('.'); if (nPos > 0 ) { pDlg->m_strWavFileName= pDlg->m_strWavFileName.Left( nPos ); } strOutDir = g_config.GetCnvOutputDir() + strSubPath; // Prepend output directory pDlg->m_strWavFileName= strOutDir + CUString( pDlg->m_strWavFileName ); // Create Ouput directory if ( CDEX_OK != DoesDirExist( strOutDir, FALSE ) ) { LTRACE( _T( "ConvertFunc::Error creating output dir %s" ), strOutDir ); strLang = g_language.GetString( IDS_CANNOT_CREATE_OUTDIR ); CDexMessageBox( strLang + strOutDir ); bErr = CDEX_ERROR; } // Clear error flag bErr = CDEX_OK; LTRACE( _T( "Converting track %d" ), pDlg->m_wCurrentTrack ); // Reset estimate timer //pDlg->m_TimeTrack.ReInit(); pDlg->m_nPercentCompleted=0; // create proper input stream pDlg->m_pInStream = ICreateStream( CUString( pDlg->m_strMP3FileName ) ); if ( FALSE == CheckNoFileOverwrite( pDlg, CUString( pDlg->m_strWavFileName ) + _W( ".wav" ), TRUE, pDlg->m_bYesToAll, bNoToAll ) ) { // Open the input stream if available if ( pDlg->m_pInStream && pDlg->m_pInStream->OpenStream( CUString( pDlg->m_strMP3FileName ) ) ) { DWORD dwBufferSize = pDlg->m_pInStream->GetBufferSize(); // Reset estimate timer dwTotalTime = pDlg->m_pInStream->GetTotalTime(); pDlg->m_TimeTrack.ReInit( dwTotalTime ); // Create a play stream object OSndStreamWAV wavStream; wavStream.CopyStreamInfo( *pDlg->m_pInStream ); // Initialize output WAV stream object wavStream.OpenStream( CUString( pDlg->m_strWavFileName ) ); // Allocate stream input buffer pStream = new BYTE[ dwBufferSize ]; int nMPEGBytes = 0; double dSampleRatio = 1.0; BOOL bFinished = FALSE; while( ( FALSE == bFinished ) && !pDlg->m_bAbortThread ) { nMPEGBytes = pDlg->m_pInStream->Read( pStream, dwBufferSize ); if ( nMPEGBytes > 0 ) { for ( dwIndex=0; dwIndex< (DWORD)nMPEGBytes / 2; dwIndex++ ) { if ( abs( ((SHORT*)pStream)[dwIndex]) > nPeakValue ) nPeakValue=abs( ((SHORT*)pStream )[ dwIndex ] ); } if ( nMPEGBytes > 0 ) { wavStream.Write( pStream, nMPEGBytes ); } int nTotalTime = pDlg->m_pInStream->GetTotalTime(); int nCurrentTime = pDlg->m_pInStream->GetCurrentTime(); if ( nTotalTime ) { pDlg->m_nPercentCompleted = nCurrentTime * 100 / nTotalTime; } else { pDlg->m_nPercentCompleted = 0; } } else { bFinished = TRUE; } } delete [] pStream; pStream= NULL; // Close input stream pDlg->m_pInStream->CloseStream(); // Close the WAV stream wavStream.CloseStream(); // close the Input stream // Check if we have to normalize the file if ( pDlg->m_pFileDlg->m_bNormalize && FALSE == pDlg->m_bAbortThread ) { double dNormFactor=1.0; // Reset estimate timer pDlg->m_TimeTrack.ReInit(dwTotalTime); // Set percentage completed to zero pDlg->m_nPercentCompleted=0; // Determine normalization factor dNormFactor=((nPeakValue-1.0)/327.68); // DO we have to normalize this file if (dNormFactor<(double)g_config.GetLowNormLevel() || dNormFactor>(double)g_config.GetHighNormLevel()) { if (dNormFactor<(double)g_config.GetLowNormLevel()) { // Normalize to for desired level dNormFactor=(double)g_config.GetLNormFactor()/dNormFactor; } else { // Normalize to for desired level dNormFactor=(double)g_config.GetHNormFactor()/dNormFactor; } // Little fine tuning to avoid overflows due to round off errors dNormFactor*=0.9999; LTRACE( _T( "CMP3ToWavDlg::Normalizing Track/File %s with factor %f" ), pDlg->m_strWavFileName, dNormFactor ); CWAV myWav; // Step 1: Open the input WAV file if ( myWav.StartNormalizeAudioFile( CUString( pDlg->m_strWavFileName ) )!=0) { // Step 2: Loop through data and normalize chunk while ( myWav.NormalizeAudioFileChunk( dNormFactor, pDlg->m_nPercentCompleted ) == FALSE && !pDlg->m_bAbortThread ) { ::Sleep(0); } // Step 3: Close the input WAV file, and replace original myWav.CloseNormalizeAudioFile( CUString( pDlg->m_strWavFileName ) , pDlg->m_bAbortThread, TRUE ); } } } // Check if thread has been aborted, if so, remove original file if ( TRUE == pDlg->m_bAbortThread ) { LTRACE( _T( "Deleting file ( due to abort ) %s.wav" ), pDlg->m_strWavFileName ); DeleteFile( pDlg->m_strWavFileName + _T( ".wav" ) ); } // Check if we have to delete the file if ( pDlg->m_pFileDlg->m_bDeleteOriginal && ( FALSE == pDlg->m_bAbortThread ) ) { LTRACE( _T( "Deleting file ( user request ) %s" ), pDlg->m_strMP3FileName ); DeleteFile( pDlg->m_strMP3FileName ); } } } else { if ( TRUE == bNoToAll ) { pDlg->m_bAbortThread = TRUE; } } // delete input stream object delete pDlg->m_pInStream;pDlg->m_pInStream=NULL; // Jump to the next track pDlg->m_wCurrentTrack++; } pDlg->m_eThreadFinished.SetEvent(); // OK close the stuff pDlg->PostMessage( WM_COMMAND, IDCANCEL,0); EXIT_TRACE( _T( "RipFunc" ) ); return 0; }
UINT CPlayerView::PlayThreadFunc(PVOID pParams) { BYTE* pStream = NULL; CDEX_ERR bErr = CDEX_OK; CPlayerView* pDlg = NULL; int nCurrentFile = -1; CString strFileName; ENTRY_TRACE( _T( "CPlayerView::PlayFunc" ) ); nCurrentFile = 0; pDlg=(CPlayerView*)pParams; pDlg->m_bAbortThread = FALSE; pDlg->m_nTotalTime = 0; pDlg->m_nCurrentTime = 0; nCurrentFile = pDlg->m_PlayList.GetCurSel( ); if ( pDlg->GetPlayRandom() ) { srand( (unsigned)time( NULL ) ); nCurrentFile = rand() % pDlg->m_vFileNames.size(); } if ( nCurrentFile < 0 ) { nCurrentFile = 0; } while( ( nCurrentFile >= 0 ) && ( nCurrentFile < (int)pDlg->m_vFileNames.size() ) && ( FALSE == pDlg->m_bAbortThread ) ) { DWORD dwStreamIndex=0; strFileName = pDlg->m_vFileNames[ nCurrentFile ]; #ifdef _DEBUG // strFileName = "http://urn.nottingham.ac.uk/urnlive.pls"; // strFileName = "http://reclib.su.nottingham.ac.uk:8080"; #endif pDlg->m_PlayList.SetCurSel( nCurrentFile ); LTRACE( _T( "Playing track %s (file %d)" ), strFileName, nCurrentFile ); pDlg->SetThreadCommand( THREAD_PLAY_NEXT_TRACK ); // Delete the old stream if it does exist if ( pDlg->m_pInStream ) { delete pDlg->m_pInStream; pDlg->m_pInStream = NULL; } // create proper input stream pDlg->m_pInStream = ICreateStream( CUString( strFileName ) ); pDlg->m_dwSeekOffset = 0; // Open the MPEG stream if (pDlg->m_pInStream->OpenStream( CUString( strFileName ) ) ) { DWORD dwInBufferSize = pDlg->m_pInStream->GetBufferSize(); int nMPEGBytes=0; // Create a play stream object pDlg->m_pPlayStream=new PlayWavStream; pDlg->m_pPlayStream->CopyStreamInfo( *pDlg->m_pInStream ); // Initialize play stream object if ( FALSE == pDlg->m_pPlayStream->OpenStream( _W( "" ) ) ) { pDlg->m_bAbortThread = TRUE; } // Allocate stream input buffer auto_ptr<BYTE> pStream( new BYTE[ dwInBufferSize + STREAMBUFFERSIZE ] ); pDlg->m_bAbortCurrent = FALSE; // Set status pDlg->m_nStatus = PLAYING; while ( ( !pDlg->m_bAbortThread ) && ( FALSE == pDlg->m_bAbortCurrent ) ) { if ( PLAYING != pDlg->m_nStatus ) { WaitForSingleObject( pDlg->m_ePaused, INFINITE ); dwStreamIndex = 0; pDlg->m_pInStream->Seek( pDlg->m_dwSeekOffset, SEEK_TIME ); } if ( pDlg->m_bAbortThread ) { break; } if ( (nMPEGBytes = pDlg->m_pInStream->Read( (BYTE*)( pStream.get() ) + dwStreamIndex,dwInBufferSize ) ) >0 ) { // increase current stream index position dwStreamIndex += nMPEGBytes ; // play the stuff when there is STREAMBUFFERSIZE samples are present while ( ( dwStreamIndex >= STREAMBUFFERSIZE ) && ( FALSE == pDlg->m_bAbortThread ) && ( FALSE == pDlg->m_bAbortCurrent ) ) { if ( PLAYING != pDlg->m_nStatus ) { break; } pDlg->m_pPlayStream->Write( pStream.get(), STREAMBUFFERSIZE ); dwStreamIndex-= STREAMBUFFERSIZE; memmove( pStream.get() , (BYTE*)pStream.get() + STREAMBUFFERSIZE, dwStreamIndex ); } pDlg->m_dwBitRate=pDlg->m_pInStream->GetBitRate(); pDlg->m_nTotalTime=pDlg->m_pInStream->GetTotalTime(); } else { while ( dwStreamIndex ) { DWORD dwBytes = min( STREAMBUFFERSIZE, dwStreamIndex ); if ( pDlg->m_bAbortThread ) { break; } if ( dwBytes < STREAMBUFFERSIZE ) { memset( (BYTE*)pStream.get() + dwBytes, 0, STREAMBUFFERSIZE - dwBytes ); } pDlg->m_pPlayStream->Write( pStream.get(), STREAMBUFFERSIZE ); dwStreamIndex-= dwBytes; if ( dwStreamIndex ) { memmove( pStream.get() , (BYTE*)pStream.get() + dwBytes, dwStreamIndex ); } } pDlg->m_bAbortCurrent = TRUE; } } } else { pDlg->MessageBox( _T( "Problem opening the file" ) ); } // Close the mpeg stream if (pDlg->m_pInStream) { pDlg->m_pInStream->CloseStream(); // Don't delete it, since we want to able to get // the file details } // Close the play stream if (pDlg->m_pPlayStream) { LTRACE( _T( "Closing the output stream !!!!" ) ); pDlg->m_pPlayStream->CloseStream(); } delete pDlg->m_pPlayStream; pDlg->m_pPlayStream = NULL; switch ( pDlg->GetThreadCommand() ) { case THREAD_PLAY_NEXT_TRACK: if ( pDlg->GetPlayRandom() ) { int nNewFile = nCurrentFile; // randomize until we got a different track while ( pDlg->m_vFileNames.size() > 1 && nCurrentFile == nNewFile ) { srand( (unsigned)time( NULL ) ); nNewFile = rand() % pDlg->m_vFileNames.size(); } nCurrentFile = nNewFile; } else { nCurrentFile++; } break; case THREAD_PLAY_PREV_TRACK: if ( nCurrentFile > 0 ) { nCurrentFile--; } break; case THREAD_PLAY_FINISH: pDlg->m_bAbortThread = TRUE; break; case THREAD_PLAY_TRACK: nCurrentFile = pDlg->m_PlayList.GetCurSel( ); break; } } pDlg->m_nStatus = IDLE; pDlg->m_pThread = NULL; pDlg->m_eThreadFinished.SetEvent(); EXIT_TRACE( _T( "CPlayerView::PlayThreadFunc" ) ); return 0; }