Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

149 lines
4.7 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Create an output wave stream. Used to record audio for in-engine movies or
  4. // mixer debugging.
  5. //
  6. //=====================================================================================//
  7. #include "audio_pch.h"
  8. // memdbgon must be the last include file in a .cpp file!!!
  9. #include "tier0/memdbgon.h"
  10. extern IFileSystem *g_pFileSystem;
  11. // FIXME: shouldn't this API be part of IFileSystem?
  12. extern bool COM_CopyFile( const char *netpath, const char *cachepath );
  13. // Create a wave file
  14. void WaveCreateTmpFile( const char *filename, int rate, int bits, int channels )
  15. {
  16. char tmpfilename[MAX_PATH];
  17. Q_StripExtension( filename, tmpfilename, sizeof( tmpfilename ) );
  18. Q_DefaultExtension( tmpfilename, ".WAV", sizeof( tmpfilename ) );
  19. FileHandle_t file;
  20. file = g_pFileSystem->Open( tmpfilename, "wb" );
  21. if ( file == FILESYSTEM_INVALID_HANDLE )
  22. return;
  23. int chunkid = LittleLong( RIFF_ID );
  24. int chunksize = LittleLong( 0 );
  25. g_pFileSystem->Write( &chunkid, sizeof(int), file );
  26. g_pFileSystem->Write( &chunksize, sizeof(int), file );
  27. chunkid = LittleLong( RIFF_WAVE );
  28. g_pFileSystem->Write( &chunkid, sizeof(int), file );
  29. // create a 16-bit PCM stereo output file
  30. PCMWAVEFORMAT fmt = { 0 };
  31. fmt.wf.wFormatTag = LittleWord( (short)WAVE_FORMAT_PCM );
  32. fmt.wf.nChannels = LittleWord( (short)channels );
  33. fmt.wf.nSamplesPerSec = LittleDWord( rate );
  34. fmt.wf.nAvgBytesPerSec = LittleDWord( rate * bits * channels / 8 );
  35. fmt.wf.nBlockAlign = LittleWord( (short)( 2 * channels ) );
  36. fmt.wBitsPerSample = LittleWord( (short)bits );
  37. chunkid = LittleLong( WAVE_FMT );
  38. chunksize = LittleLong( sizeof(fmt) );
  39. g_pFileSystem->Write( &chunkid, sizeof(int), file );
  40. g_pFileSystem->Write( &chunksize, sizeof(int), file );
  41. g_pFileSystem->Write( &fmt, sizeof( PCMWAVEFORMAT ), file );
  42. chunkid = LittleLong( WAVE_DATA );
  43. chunksize = LittleLong( 0 );
  44. g_pFileSystem->Write( &chunkid, sizeof(int), file );
  45. g_pFileSystem->Write( &chunksize, sizeof(int), file );
  46. g_pFileSystem->Close( file );
  47. }
  48. void WaveAppendTmpFile( const char *filename, void *pBuffer, int sampleBits, int numSamples )
  49. {
  50. char tmpfilename[MAX_PATH];
  51. Q_StripExtension( filename, tmpfilename, sizeof( tmpfilename ) );
  52. Q_DefaultExtension( tmpfilename, ".WAV", sizeof( tmpfilename ) );
  53. FileHandle_t file;
  54. file = g_pFileSystem->Open( tmpfilename, "r+b" );
  55. if ( file == FILESYSTEM_INVALID_HANDLE )
  56. return;
  57. g_pFileSystem->Seek( file, 0, FILESYSTEM_SEEK_TAIL );
  58. if ( IsGameConsole() && sampleBits == 16 )
  59. {
  60. short *pSwapped = (short * )stackalloc( numSamples * sampleBits/8 );
  61. for ( int i=0; i<numSamples; i++ )
  62. {
  63. pSwapped[i] = LittleShort( ((short*)pBuffer)[i] );
  64. }
  65. g_pFileSystem->Write( pSwapped, numSamples * sizeof( short ), file );
  66. }
  67. else
  68. {
  69. g_pFileSystem->Write( pBuffer, numSamples * sampleBits/8, file );
  70. }
  71. g_pFileSystem->Close( file );
  72. }
  73. void WaveFixupTmpFile( const char *filename )
  74. {
  75. char tmpfilename[MAX_PATH];
  76. Q_StripExtension( filename, tmpfilename, sizeof( tmpfilename ) );
  77. Q_DefaultExtension( tmpfilename, ".WAV", sizeof( tmpfilename ) );
  78. FileHandle_t file;
  79. file = g_pFileSystem->Open( tmpfilename, "r+b" );
  80. if ( FILESYSTEM_INVALID_HANDLE == file )
  81. {
  82. Warning( "WaveFixupTmpFile( '%s' ) failed to open file for editing\n", tmpfilename );
  83. return;
  84. }
  85. // file size goes in RIFF chunk
  86. int size = g_pFileSystem->Size( file ) - 2*sizeof( int );
  87. // offset to data chunk
  88. int headerSize = (sizeof(int)*5 + sizeof(PCMWAVEFORMAT));
  89. // size of data chunk
  90. int dataSize = size - headerSize;
  91. size = LittleLong( size );
  92. g_pFileSystem->Seek( file, sizeof( int ), FILESYSTEM_SEEK_HEAD );
  93. g_pFileSystem->Write( &size, sizeof( int ), file );
  94. // skip the header and the 4-byte chunk tag and write the size
  95. dataSize = LittleLong( dataSize );
  96. g_pFileSystem->Seek( file, headerSize+sizeof( int ), FILESYSTEM_SEEK_HEAD );
  97. g_pFileSystem->Write( &dataSize, sizeof( int ), file );
  98. g_pFileSystem->Close( file );
  99. }
  100. CON_COMMAND( movie_fixwave, "Fixup corrupted .wav file if engine crashed during startmovie/endmovie, etc." )
  101. {
  102. if ( args.ArgC() != 2 )
  103. {
  104. Msg ("Usage: movie_fixwave wavname\n");
  105. return;
  106. }
  107. char const *wavname = args.Arg( 1 );
  108. if ( !g_pFileSystem->FileExists( wavname ) )
  109. {
  110. Warning( "movie_fixwave: File '%s' does not exist\n", wavname );
  111. return;
  112. }
  113. char tmpfilename[256];
  114. Q_StripExtension( wavname, tmpfilename, sizeof( tmpfilename ) );
  115. Q_strncat( tmpfilename, "_fixed", sizeof( tmpfilename ), COPY_ALL_CHARACTERS );
  116. Q_DefaultExtension( tmpfilename, ".wav", sizeof( tmpfilename ) );
  117. // Now copy the file
  118. Msg( "Copying '%s' to '%s'\n", wavname, tmpfilename );
  119. COM_CopyFile( wavname, tmpfilename );
  120. Msg( "Performing fixup on '%s'\n", tmpfilename );
  121. WaveFixupTmpFile( tmpfilename );
  122. }