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

  1. /* 
  2.  *  AudioPlayback.cpp 
  3.  *
  4.  *    Copyright (C) Alberto Vigata - January 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. #include <windows.h>
  25. #include <mmsystem.h>
  26. #include <malloc.h>
  27. #include <winbase.h>
  28.  
  29. #include "AudioPlayback.h"
  30. #include "../debug.h"
  31.  
  32. #define BUFFER_COUNT 20
  33. #define BUFFER_SIZE  16384
  34. #define BUFFER_SIZE_TOTAL (BUFFER_SIZE*BUFFER_COUNT)
  35.  
  36. // #define PRINT_STATS
  37.  
  38. #define WHDR_READYTOSEND 0x1
  39.  
  40. // Global static module variables
  41. static HWAVEOUT hWaveOut;
  42. static HANDLE   hAudioEv;
  43. static unsigned char buffers[BUFFER_COUNT][BUFFER_SIZE];
  44. static WAVEHDR        wav_hdr[BUFFER_COUNT];
  45.  
  46. // Init sound output system
  47. int AudioPlaybackStart(TAudioPlayback *ap)
  48. {
  49.     WAVEFORMATEX waveFormat;
  50.     int i;
  51.  
  52.     if(!ap)
  53.         return 0;
  54.     // chunk_size must be a multiple of the audio buffer
  55.     if(ap->chunk_size%BUFFER_SIZE != 0)
  56.         return 0;
  57.  
  58.     waveFormat.wFormatTag       = WAVE_FORMAT_PCM;
  59.     waveFormat.nChannels        = ap->n_channels;
  60.     waveFormat.nSamplesPerSec   = ap->sample_freq; 
  61.     waveFormat.wBitsPerSample   = 16;
  62.     waveFormat.nBlockAlign      = waveFormat.nChannels * 
  63.                                   waveFormat.wBitsPerSample /8;
  64.     waveFormat.nAvgBytesPerSec  = waveFormat.nSamplesPerSec *
  65.                                   waveFormat.nBlockAlign; 
  66.     waveFormat.cbSize           = 0; 
  67.  
  68.  
  69.     // Create an event for signaling finished work with audio blocks
  70.     hAudioEv = CreateEvent(NULL, FALSE, FALSE, NULL);
  71.  
  72.     if(    waveOutOpen(  &hWaveOut, 
  73.                          WAVE_MAPPER, 
  74.                          &waveFormat, 
  75.                          (DWORD)hAudioEv, 
  76.                          0, 
  77.                          CALLBACK_EVENT)
  78.         != MMSYSERR_NOERROR )
  79.         return 0;
  80.  
  81.     // Prepare audio blocks
  82.     for(i=0; i<BUFFER_COUNT; i++)
  83.     {
  84.         wav_hdr[i].lpData          = (LPSTR) buffers[i];
  85.         wav_hdr[i].dwBufferLength  = BUFFER_SIZE;
  86.         if( waveOutPrepareHeader( hWaveOut, &wav_hdr[i], sizeof(wav_hdr[i]) )
  87.             != MMSYSERR_NOERROR )
  88.             return 0;
  89.         // if no error, set the audio blocks as done
  90.         wav_hdr[i].dwFlags         |= WHDR_DONE;
  91.     wav_hdr[i].dwUser          = 0;
  92.     }
  93.  
  94.  
  95.     return 1;
  96. }
  97.  
  98. // Removes all buffers, and resets audio playback
  99. int AudioPlayBackReset()
  100. {
  101.   waveOutReset( hWaveOut );
  102.   return 0;
  103. }
  104.  
  105.  
  106. int AudioGetBufferDelay(TAudioPlayback *ap)
  107. {
  108.     int i, nBufferedData = 0;
  109.     for(i=0; i<BUFFER_COUNT; i++)
  110.     {
  111.         // If the buffer is not done
  112.         if( !(wav_hdr[i].dwFlags & WHDR_DONE) )
  113.             nBufferedData += wav_hdr[i].dwBufferLength;
  114.     }
  115.     return (nBufferedData * 1000)/(ap->sample_freq * ap->n_channels * 2);
  116. }
  117.  
  118. int PrintStats(TAudioPlayback *ap)
  119. {
  120.   //  Gather amount of data in buffers
  121.   int i, nBufferedData = 0;
  122.   for(i=0; i<BUFFER_COUNT; i++)
  123.   {
  124.     // If the buffer is not done
  125.     if( !(wav_hdr[i].dwFlags & WHDR_DONE) )
  126.       nBufferedData += wav_hdr[i].dwBufferLength;
  127.   }
  128.  
  129.  
  130.   int nPercent = (nBufferedData * 100)/BUFFER_SIZE_TOTAL;
  131.     int nDelayBuffer = (nBufferedData * 1000)/(ap->sample_freq * ap->n_channels * 2);
  132.   // Spit stats
  133.   DBG_STR((str, "Audio Buffer State: %d/%d -> %d%%, %d ms\n", nBufferedData, 
  134.                                                              BUFFER_SIZE_TOTAL,
  135.                                                              nPercent,
  136.                                                             nDelayBuffer))
  137.   return 0;
  138. }
  139.  
  140.  
  141. int AudioPlaybackWrite(TAudioPlayback *ap, unsigned char *data)
  142. {
  143.     int remaining_bytes = ap->chunk_size;
  144.     int i;
  145. #ifdef PRINT_STATS
  146.   DBG_STR(( str, "------------\n"))
  147.   PrintStats(ap);
  148. #endif
  149.  
  150.  
  151.   // fill those blocks that have been played
  152.   //      and put them into the queue
  153.   for(i=0; i<BUFFER_COUNT; i++)
  154.     if( (wav_hdr[i].dwFlags & WHDR_DONE) && remaining_bytes)
  155.     {
  156.       memcpy(buffers[i], &data[ ap->chunk_size - remaining_bytes ], BUFFER_SIZE);
  157.       wav_hdr[i].dwUser = WHDR_READYTOSEND;
  158.       remaining_bytes -= BUFFER_SIZE;
  159.     }
  160.  
  161.  
  162.   // Now send the ones that are ready to send
  163.     for(i=0; i<BUFFER_COUNT; i++)
  164.     if( (wav_hdr[i].dwUser & WHDR_READYTOSEND) ) 
  165.     {
  166.       waveOutWrite( hWaveOut, &wav_hdr[i], sizeof(wav_hdr[i]) );
  167.       wav_hdr[i].dwUser = 0;
  168.     }
  169.  
  170.   // And now keep sending blocks until you are 
  171.   // finished with your data
  172.      while( remaining_bytes )
  173.     {
  174.         // fill those blocks that have been played
  175.         //      and put them into the queue
  176.         for(i=0; i<BUFFER_COUNT; i++)
  177.             if( (wav_hdr[i].dwFlags & WHDR_DONE) && remaining_bytes)
  178.             {
  179.                 memcpy(buffers[i], &data[ ap->chunk_size - remaining_bytes ], BUFFER_SIZE);
  180.                 waveOutWrite( hWaveOut, &wav_hdr[i], sizeof(wav_hdr[i]) );
  181.                 remaining_bytes -= BUFFER_SIZE;
  182.             }
  183.         // if there is no more data to write, exit
  184.         if(!remaining_bytes)
  185.             break;
  186.         // wait for finished buffers
  187.         WaitForSingleObject(hAudioEv, INFINITE);
  188.     }
  189.  
  190. #ifdef PRINT_STATS
  191.   PrintStats(ap);
  192.   DBG_STR(( str, "------------\n"))
  193. #endif
  194.  
  195.     return 1;
  196. }
  197.  
  198. int AudioPlaybackStop(TAudioPlayback *ap)
  199. {
  200.     int i;
  201.     waveOutReset( hWaveOut );
  202.     waveOutClose( hWaveOut );
  203.     // UnPrepare audio blocks
  204.     for(i=0; i<BUFFER_COUNT; i++)
  205.     {
  206.         waveOutUnprepareHeader( hWaveOut, &wav_hdr[i], sizeof(wav_hdr[i]) );
  207.     }
  208.     return 1;
  209. }