home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2004 March / PCWELT_3_2004.ISO / pcwsoft / flaskmpeg_078_39_src.z.exe / flaskmpeg / audioproperties.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2002-10-28  |  12.6 KB  |  434 lines

  1. /* 
  2.  *  AudioProperties.cpp 
  3.  *
  4.  *    Copyright (C) Alberto Vigata - July 2000 - ultraflask@yahoo.com
  5.  *
  6.  *  This file is part of FlasKMPEG, a free MPEG to MPEG/AVI converter
  7.  *    
  8.  *  FlasKMPEG is free software; you can redistribute it and/or modify
  9.  *  it under the terms of the GNU General Public License as published by
  10.  *  the Free Software Foundation; either version 2, or (at your option)
  11.  *  any later version.
  12.  *   
  13.  *  FlasKMPEG is distributed in the hope that it will be useful,
  14.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  *  GNU General Public License for more details.
  17.  *   
  18.  *  You should have received a copy of the GNU General Public License
  19.  *  along with GNU Make; see the file COPYING.  If not, write to
  20.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  21.  *
  22.  */
  23.  
  24.  
  25.  
  26. #include "FlasKMPEG.h"
  27. #include "auxiliary.h"
  28. #include "resource.h"
  29. #include "Player.h"
  30. #include "debug.h"
  31. #include "AudioProperties.h"
  32. #include "./RunState.h"
  33. #include "./Audio/AudioPlayback.h"
  34. #include "./Misc/StatsStrings.h"
  35. #include <string>
  36.  
  37. // Extern globals
  38. extern TConfig          o;
  39. extern TRunState        rs;
  40. extern HINSTANCE        hInst;
  41. extern HWND                hMainWnd;
  42.  
  43. // Local variables
  44. static HWND                 hPlayerDlg;
  45. static CAudioThread         *g_pAudioThread;
  46.  
  47. #define NORMSLIDER_MAX 200
  48. #undef AUDIO_PLAYBACK_TRACE
  49.  
  50. const int nTrackBarRange = 1000;
  51.  
  52. extern TProfile pprof; // the player profile. Use this only
  53.  
  54.  
  55. // Actual running thread
  56. DWORD CAudioThread::ThreadProc()
  57. {
  58.   m_nState = stStopped;
  59.   bool bAudioAvailable;
  60.  
  61.   TCommand sCommand;
  62.  
  63.   ui32 nSamplesPlayed=0; // This is our way to keep track of time with audio
  64.   mmtick tkPresTime;
  65.  
  66.   m_tkSensThreshold = 1000;
  67.  
  68.   pprof.sAudioProperties.sAudioTrack = rs.sAudioTrack; 
  69.  
  70.   TAudioPlayback sAudioPlayback;
  71.   unsigned char *data;
  72.   sAudioPlayback.n_channels = 2;
  73.   if (pprof.sampleFreqSameAsInput)
  74.     sAudioPlayback.sample_freq = rs.audio->sampleRate;
  75.   else
  76.     sAudioPlayback.sample_freq = pprof.outSampleFrequency; 
  77.   sAudioPlayback.chunk_size = 16384*2;
  78.  
  79.   bAudioAvailable = AudioPlaybackStart(&sAudioPlayback) > 0;
  80.   SetPriority(THREAD_PRIORITY_ABOVE_NORMAL);
  81.   
  82.   while(1)
  83.   {
  84.     // open scope to lock command
  85.     if( GetCommand(&sCommand) )
  86.     {
  87.       switch( sCommand.nCommand )
  88.       {
  89.       case noCommand:
  90.         break;
  91.       case seek:      
  92.         if(rs.audio )
  93.         {
  94.           if(m_nState!=stStopped)
  95.             rs.audio->Stop();
  96.           rs.audio->SetStreamPos(sCommand.nParam);
  97.           rs.audio->Start(sAudioPlayback.sample_freq, DO_AUDIO|AUDIO_PREVIEW, &pprof.sAudioProperties);
  98.           m_nState = stStopped;          
  99.         }
  100.         break;
  101.       case play:
  102.         if(rs.audio && bAudioAvailable )
  103.         {
  104.           if(m_nState!=stStopped)
  105.             rs.audio->Stop();
  106.  
  107.           nSamplesPlayed = 0;
  108.           rs.audio->Start(sAudioPlayback.sample_freq, DO_AUDIO|AUDIO_PREVIEW, &pprof.sAudioProperties);
  109.           m_nState = stPlaying;
  110.         }
  111.         break;
  112.       case trackChange:
  113.         if(rs.audio )       
  114.         {
  115.           TAudioTrack *pTrack = (TAudioTrack *)sCommand.nParam;
  116.           rs.audio->SetTrack(pTrack);
  117.         }
  118.         break;
  119.       case stop:
  120.         if(rs.audio )
  121.         {          
  122.           if(m_nState!=stStopped)
  123.             rs.audio->Stop();
  124.         
  125.           if(bAudioAvailable)
  126.             AudioPlayBackReset();
  127.  
  128.           m_nState = stStopped;        
  129.         }
  130.         break;
  131.       case normalize:
  132.         if(rs.audio )
  133.         {         
  134.           if(m_nState!=stStopped)
  135.             rs.audio->Stop();
  136.           rs.audio->SetStreamPos(0);
  137.           rs.audio->Start(sAudioPlayback.sample_freq, 
  138.                           DO_AUDIO|AUDIO_PREVIEW|AUDIO_DONT_NORMALIZE, 
  139.                           &pprof.sAudioProperties );
  140.           m_nState = stNormalizing;
  141.         }
  142.         break;
  143.       case exit:
  144.         if(m_nState!=stStopped && rs.audio)
  145.           rs.audio->Stop();
  146.  
  147.         ReplyCommand(&sCommand);
  148.         goto end;
  149.         break;
  150.       }
  151.  
  152.       ReplyCommand(&sCommand);
  153.     }
  154.     else // No command. Wait if stopped
  155.     {
  156.       if(m_nState==stStopped)
  157.         WaitCommand();
  158.     }
  159.  
  160.     // Perform action according the state of the playe
  161.     
  162.     
  163.     switch(m_nState)
  164.     {
  165.     case stStopped:
  166.       break;    
  167.     case stPlaying:
  168.       if( !rs.audio->GetSamples(0, (short **)&data, (sAudioPlayback.chunk_size)>>2) )
  169.       {
  170.         rs.audio->Stop();
  171.         
  172.         if(bAudioAvailable)
  173.           AudioPlayBackReset();
  174.  
  175.         m_nState = stStopped; 
  176.         continue;
  177.       }
  178.  
  179.       // DBG_STR((str, "Starting Audio Playing at %I64d ms\n", m_pMasterClock->GetTickCount()/10 ))
  180.  
  181.       nSamplesPlayed += (sAudioPlayback.chunk_size)>>2;
  182.  
  183.       // Calculate the presentation time of the first sample of this chunk
  184.       tkPresTime = ((mmtick)nSamplesPlayed * (mmtick)10000) /(mmtick)sAudioPlayback.sample_freq;
  185.       
  186.         // Adjust the presentation time taking into account
  187.         // the amount of data currently in the audio buffer
  188.       if(bAudioAvailable)
  189.       {
  190.         m_pMasterClock->Set( tkPresTime - AudioGetBufferDelay(&sAudioPlayback)*10);
  191.         AudioPlaybackWrite(&sAudioPlayback, data);
  192.       }
  193.  
  194.  
  195.  
  196.       break;      
  197.     case stNormalizing:
  198.       rs.audio->GetSamples(0, (short **)&data, (sAudioPlayback.chunk_size)>>2);
  199.       nSamplesPlayed += (sAudioPlayback.chunk_size)>>2;
  200.  
  201.       ui16 max = FindMax((i16*)data, sAudioPlayback.chunk_size);
  202.       if(  max >= m_nMaxSample )
  203.         m_nMaxSample = max;
  204.       break;
  205.     }
  206.  
  207.   }
  208.  
  209. end:
  210.   if(bAudioAvailable)  
  211.     AudioPlaybackStop(&sAudioPlayback); 
  212.   // Exit
  213.   return 0;
  214. }
  215.  
  216.  
  217.  
  218. void RenderMCSlider(HWND hDlg, int sliderID, int sliderDB, int value)
  219. {
  220.   char szTemp[256];
  221.  
  222.   SendDlgItemMessage(hDlg, sliderID, TBM_SETRANGE, 
  223.     (WPARAM) TRUE, (LPARAM) MAKELONG(0, TAUDIOPROPERTIES_MCHANNEL_MAX_RANGE*2));
  224.  
  225.  
  226.   sprintf(szTemp, "%s%1.2f dB", value>0?"+":"", ((float)(value)/(float)100));
  227.   DlgSetText( hDlg, sliderDB, szTemp );
  228.  
  229.   value += TAUDIOPROPERTIES_MCHANNEL_MAX_RANGE;
  230.   value = TAUDIOPROPERTIES_MCHANNEL_MAX_RANGE*2 - value;
  231.   // Set the track position
  232.   SendDlgItemMessage(hDlg, sliderID, TBM_SETPOS, (WPARAM) (BOOL) true,(LPARAM) (LONG) value);
  233. }
  234.  
  235. // Activate, de-activate sliders
  236. void RenderSliders(HWND hDlg, TAudioProperties *pAudProps, TStatsStrings &st)
  237. {
  238.   DlgCheck(hDlg, IDC_DRCCHECK, pAudProps->drc );
  239.   DlgEnable(hDlg, IDC_DRCSLIDER, pAudProps->drc);
  240.   DlgEnable(hDlg, IDC_NORMSLIDER, pAudProps->normalize);
  241.  
  242.   DlgCheck(hDlg, IDC_NORMCHECK, pAudProps->normalize );
  243.   DlgEnable(hDlg, IDC_NORMSEARCH, pAudProps->normalize);
  244.   DlgEnable(hDlg, IDC_NORMEDIT, pAudProps->normalize);
  245.   DlgSetText(hDlg, IDC_NORMEDIT, pAudProps->normalize_value );
  246.  
  247.   // NORM slider
  248.   SendDlgItemMessage(hDlg, IDC_NORMSLIDER, TBM_SETRANGE, 
  249.     (WPARAM) TRUE, (LPARAM) MAKELONG(0, NORMSLIDER_MAX));
  250.   
  251.   SendDlgItemMessage(hDlg, IDC_NORMSLIDER, TBM_SETPOS, 
  252.     (WPARAM) (BOOL) true,
  253.     (LPARAM) (LONG) NORMSLIDER_MAX - pAudProps->normalize_value);
  254.   
  255.   
  256.   DlgCheck(hDlg, IDC_DOLBYDOWNMIX, pAudProps->dolby_surround_downmix );
  257.   DlgCheck(hDlg, IDC_MCCHECK, pAudProps->multichannel_volume );
  258.   DlgEnable(hDlg, IDC_MCCENTER, pAudProps->multichannel_volume);
  259.   DlgEnable(hDlg, IDC_MCFRONT, pAudProps->multichannel_volume);
  260.   DlgEnable(hDlg, IDC_MCREAR, pAudProps->multichannel_volume);
  261.   DlgEnable(hDlg, IDC_MCRESET, pAudProps->multichannel_volume);
  262.  
  263.   // Now set the value
  264.  
  265.   // DRC
  266.   SendDlgItemMessage(hDlg, IDC_DRCSLIDER, TBM_SETRANGE, 
  267.     (WPARAM) TRUE, (LPARAM) MAKELONG(0, COMPRESSOR_STEPS));
  268.  
  269.   SendDlgItemMessage(hDlg, IDC_DRCSLIDER, TBM_SETPOS, 
  270.     (WPARAM) (BOOL) true,
  271.     (LPARAM) (LONG) COMPRESSOR_STEPS - pAudProps->drc_value);
  272.  
  273.   DlgSetText( hDlg, IDC_PROPSFORMAT, st.InMedia.audio_format );
  274.   DlgSetText( hDlg, IDC_PROPSBITRATE, st.InMedia.audio_bit_rate );
  275.   DlgSetText( hDlg, IDC_PROPSMODE, st.InMedia.audio_channels );
  276.   DlgSetText( hDlg, IDC_PROPSSAMPLEFREQ, st.InMedia.audio_sample_freq );
  277.  
  278.   // Finally set the values to the audio renderer
  279.   rs.audio->SetAudioProperties(pAudProps);
  280. }
  281.  
  282. void EndAudioProperties( HWND hDlg)
  283. {
  284.   KillTimer(hDlg, 2);
  285.  
  286.   return;
  287. }
  288. LRESULT CALLBACK AudioPropertiesDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  289. {
  290.   static DWORD lPosition;
  291.   static ui64 nFilePos;
  292.   static bool userIsTracking;
  293.   static int  nFirstAudioId;
  294.   static TStatsStrings st;
  295.   int i;
  296.  
  297.     switch (message) 
  298.     {
  299.     case WM_TIMER:
  300.       RenderInaudioStatsStrings( &st );
  301.       RenderSliders(hDlg, &pprof.sAudioProperties, st );
  302.       break;
  303.         case WM_INITDIALOG:
  304.       // First of all check to see that in fact there is audio here
  305.       if(!rs.audio)
  306.         return FALSE;
  307.  
  308.       RenderStatsStrings(&st);
  309.  
  310.       RenderSliders(hDlg, &pprof.sAudioProperties, st);
  311.  
  312.       // Fill tracks list from working mism
  313.       fmStreamId strId;
  314.       GetFirstAudioId(&rs.sStreamIds, &strId, &nFirstAudioId);
  315.       for(i=0; i<rs.sStreamIds.idCount; i++)
  316.       {
  317.         if( MismIsAudioId(&rs.sStreamIds.vIds[i]) )
  318.           ListAddText(GetDlgItem(hDlg, IDC_TRACKS), rs.sStreamIds.vIds[i].streamName);
  319.       }
  320.  
  321.       // select the default one
  322.       ListSetCur(GetDlgItem(hDlg, IDC_TRACKS), rs.sStreamIds.idAudioDef - nFirstAudioId);
  323.       
  324.       // set as toolbar
  325.       SetWindowLong( hDlg, GWL_EXSTYLE, WS_EX_TOOLWINDOW );
  326.       // Create timer
  327.       SetTimer(hDlg, 2, 500,  NULL );
  328.  
  329.       return TRUE;
  330.  
  331.     case WM_VSCROLL:
  332.       {
  333.         int range = TAUDIOPROPERTIES_MCHANNEL_MAX_RANGE;
  334.  
  335.         pprof.sAudioProperties.drc_value = 
  336.            COMPRESSOR_STEPS - SendDlgItemMessage(hDlg, IDC_DRCSLIDER, TBM_GETPOS, 0, 0 );
  337.  
  338.         pprof.sAudioProperties.normalize_value =
  339.            NORMSLIDER_MAX - SendDlgItemMessage(hDlg, IDC_NORMSLIDER, TBM_GETPOS, 0, 0 );
  340.  
  341.         RenderSliders(hDlg, &pprof.sAudioProperties, st);
  342.       }
  343.       break;
  344.         case WM_COMMAND:
  345.       switch( HIWORD(wParam))
  346.       {
  347.       case EN_UPDATE:
  348.         pprof.sAudioProperties.normalize_value = DlgGetText(hDlg, IDC_NORMEDIT);
  349.         rs.audio->SetAudioProperties( &pprof.sAudioProperties );
  350.         break;
  351.       case CBN_SELCHANGE:
  352.         {
  353.           int nSelected = ListGetCur(GetDlgItem(hDlg, IDC_TRACKS));
  354.           rs.sAudioTrack.nStreamId = rs.sStreamIds.vIds[nSelected+nFirstAudioId].streamId;
  355.           rs.sAudioTrack.nSubStreamId = rs.sStreamIds.vIds[nSelected+nFirstAudioId].subStreamId;
  356.  
  357.           pprof.sAudioProperties.sAudioTrack = rs.sAudioTrack;
  358.  
  359.           g_pAudioThread->SendCommand( CAudioThread::trackChange, 
  360.                                        (ui64)&rs.sAudioTrack );
  361.           RenderSliders(hDlg, &pprof.sAudioProperties, st);
  362.         }
  363.         break;
  364.       }
  365.             switch( LOWORD(wParam))
  366.       {
  367.       case IDOK:
  368.         CloseAudioPanel();
  369.         break;
  370.       case IDCANCEL:
  371.         break;
  372.  
  373.       case IDC_DRCCHECK:
  374.         pprof.sAudioProperties.drc = DlgIsChecked(hDlg, IDC_DRCCHECK);
  375.         RenderSliders(hDlg, &pprof.sAudioProperties, st);
  376.         break;
  377.       case IDC_NORMCHECK:
  378.         pprof.sAudioProperties.normalize = DlgIsChecked(hDlg, IDC_NORMCHECK);
  379.         RenderSliders(hDlg, &pprof.sAudioProperties, st);
  380.         break;
  381.       case IDC_MCCHECK:
  382.         pprof.sAudioProperties.multichannel_volume = DlgIsChecked(hDlg, IDC_MCCHECK);
  383.         RenderSliders(hDlg, &pprof.sAudioProperties, st);
  384.         break;
  385.       case IDC_MCRESET:
  386.         pprof.sAudioProperties.front = 
  387.         pprof.sAudioProperties.center = 
  388.         pprof.sAudioProperties.rear = 0;
  389.  
  390.         RenderSliders(hDlg, &pprof.sAudioProperties, st);
  391.         break;
  392.       case IDC_DOLBYDOWNMIX:
  393.         pprof.sAudioProperties.dolby_surround_downmix = DlgIsChecked(hDlg, IDC_DOLBYDOWNMIX);
  394.         RenderSliders(hDlg, &pprof.sAudioProperties, st);
  395.         break;
  396.       case IDC_NORMSEARCH:
  397.         break;
  398.       case IDC_SLIDER:
  399.         break;
  400.       case IDC_PLAY:
  401.         break;
  402.       case IDC_STOP:
  403.         break;
  404.       }
  405.     break;
  406.     }
  407.   return FALSE;
  408. }
  409.  
  410. void ShowAudioPanel(CAudioThread *pAudioThread)
  411. {
  412.     if(!hPlayerDlg)
  413.     {
  414.         g_pAudioThread = pAudioThread;
  415.  
  416.         hPlayerDlg = CreateDialog( hInst, 
  417.                                    MAKEINTRESOURCE(IDD_AUDIOPROPERTIES), 
  418.                                    hMainWnd, 
  419.                                    (DLGPROC) AudioPropertiesDlg );
  420.         ShowWindow( hPlayerDlg, SW_SHOW );
  421.  
  422.     }
  423. }
  424.  
  425. void CloseAudioPanel()
  426. {
  427.     if(hPlayerDlg)
  428.     {
  429.         EndAudioProperties( hPlayerDlg );
  430.         DestroyWindow( hPlayerDlg );        
  431.     }
  432.     hPlayerDlg = NULL;
  433. }
  434.