![]() |
TX Library Help – Version: 00173a, Revision: 173
|
00001 //{================================================================================================================ 00004 // @mainpage 00020 // $Copyright: (C) Ded (Ilya Dedinsky, http://txlib.ru) <mail@txlib.ru> $ 00021 //----------------------------------------------------------------------------------------------------------------- 00024 //}================================================================================================================ 00025 00026 #ifndef __TXWAVE_INCLUDED 00027 #define __TXWAVE_INCLUDED 00028 00029 //================================================================================================================= 00030 00031 #include "TXLib.h" 00032 #include <limits.h> 00033 00034 #if !(defined (_TX_VER) && (_TX_VER >= 0x173a0105)) 00035 #error Must use TXLib.h version >= 1.73a, revision >= 105 to compile TXWave. 00036 #endif 00037 00038 #if defined (_MSC_VER) 00039 #pragma warning (push) 00040 #pragma warning (disable: 4068) // Unknown pragma 00041 #pragma warning (disable: 4200) // Nonstandard extension used: zero-sized array in struct/union 00042 #pragma warning (disable: 28159) // Consider using 'GetTickCount64' instead of 'GetTickCount' 00043 #endif 00044 00045 //================================================================================================================= 00046 00047 #if defined (TX_COMPILED) && defined (TX_COMPILING) 00048 #undef TX_COMPILED 00049 #endif 00050 00051 #if !defined (TX_COMPILED) && !defined (TX_COMPILING) 00052 00053 #define _TX_BEGIN_NAMESPACE namespace { namespace TX { 00054 #define _TX_END_NAMESPACE } } 00055 00056 #else 00057 00058 #define _TX_BEGIN_NAMESPACE namespace TX { 00059 #define _TX_END_NAMESPACE } 00060 00061 #endif 00062 00063 //================================================================================================================= 00064 00067 _TX_BEGIN_NAMESPACE 00068 00071 //{---------------------------------------------------------------------------------------------------------------- 00076 //}---------------------------------------------------------------------------------------------------------------- 00077 00078 const double txWaveSampleRate = 44.100; 00079 00080 //{---------------------------------------------------------------------------------------------------------------- 00089 //}---------------------------------------------------------------------------------------------------------------- 00090 00091 const WAVEFORMATEX txWaveFormat = { WAVE_FORMAT_PCM, 2, (DWORD) (txWaveSampleRate*1000), 00092 (DWORD) (txWaveSampleRate*1000) * 2*16/8, 2*16/8, 16 }; 00093 00094 //{---------------------------------------------------------------------------------------------------------------- 00100 //}---------------------------------------------------------------------------------------------------------------- 00101 00102 const double txWaveVolMax = ((1 << txWaveFormat.wBitsPerSample) - 1) / 2.0; 00103 00104 //{---------------------------------------------------------------------------------------------------------------- 00124 //}---------------------------------------------------------------------------------------------------------------- 00125 00126 union txWaveSample_t 00127 { 00129 00130 short ch[2]; 00131 00133 00134 inline operator short*() { return ch; } 00135 }; 00136 00137 //{---------------------------------------------------------------------------------------------------------------- 00163 //}---------------------------------------------------------------------------------------------------------------- 00164 00165 typedef std::vector <txWaveSample_t> txWaveData_t; 00166 00167 //{---------------------------------------------------------------------------------------------------------------- 00231 //}---------------------------------------------------------------------------------------------------------------- 00232 00233 HWAVEOUT txWaveOut (int timeMs = -INT_MAX, 00234 double freqL = 0, double volL = 50, 00235 double freqR = -1, double volR = -1, 00236 int loops = 1, 00237 const txWaveData_t& data = txWaveData_t()); 00238 00239 //{---------------------------------------------------------------------------------------------------------------- 00281 //}---------------------------------------------------------------------------------------------------------------- 00282 00283 HWAVEOUT txWaveOut (const txWaveData_t& data, int loops = 1); 00284 00285 //{---------------------------------------------------------------------------------------------------------------- 00298 //}---------------------------------------------------------------------------------------------------------------- 00299 00300 typedef bool MonitorProc_t (HWAVEIN waveIn, txWaveData_t& data, void* userData); 00301 00302 //{---------------------------------------------------------------------------------------------------------------- 00337 //}---------------------------------------------------------------------------------------------------------------- 00338 00339 #ifdef FOR_DOXYGEN_ONLY 00340 bool MonitorProc (HWAVEIN waveIn, txWaveData_t& data, void* userData); 00341 #endif 00342 00343 //{---------------------------------------------------------------------------------------------------------------- 00369 //}---------------------------------------------------------------------------------------------------------------- 00370 00371 txWaveData_t txWaveIn (int timeMs, 00372 MonitorProc_t* monitorProc = NULL, void* monitorData = NULL, 00373 unsigned frameTime = 0); 00374 00375 //{---------------------------------------------------------------------------------------------------------------- 00396 //}---------------------------------------------------------------------------------------------------------------- 00397 00398 unsigned long txWaveGetPosition (void* wave); 00399 00400 //{---------------------------------------------------------------------------------------------------------------- 00422 //}---------------------------------------------------------------------------------------------------------------- 00423 00424 txWaveData_t txWaveLoadWav (const char filename[]); 00425 00426 //{---------------------------------------------------------------------------------------------------------------- 00441 //}---------------------------------------------------------------------------------------------------------------- 00442 00443 bool txWaveSaveWav (const txWaveData_t& data, const char filename[]); 00444 00445 //{---------------------------------------------------------------------------------------------------------------- 00460 //}---------------------------------------------------------------------------------------------------------------- 00461 00462 #define CALLOC( type, size ) ( (type*) calloc ((size), sizeof (type)) ) 00463 00464 //{---------------------------------------------------------------------------------------------------------------- 00476 //}---------------------------------------------------------------------------------------------------------------- 00477 00478 #define FREE( ptr ) ( free (ptr), (ptr) = NULL ) 00479 00480 //----------------------------------------------------------------------------------------------------------------- 00481 00484 _TX_END_NAMESPACE 00485 00488 //{---------------------------------------------------------------------------------------------------------------- 00502 //}---------------------------------------------------------------------------------------------------------------- 00503 00504 inline void* operator new (size_t size, int /* = 0 */) { return ::memset (::new char [size], 0, size); } 00505 00506 //{---------------------------------------------------------------------------------------------------------------- 00521 //}---------------------------------------------------------------------------------------------------------------- 00522 00523 inline void* operator new (size_t size, size_t items, int /* = 0 */) { return ::new (0) char [size * items]; } 00524 00527 _TX_BEGIN_NAMESPACE 00528 00531 #if !defined (TX_COMPILED) 00532 00533 //{================================================================================================================ 00534 00535 namespace Win32 00536 { 00537 _TX_DLLIMPORT ("WinMM", MMRESULT, waveOutOpen, (HWAVEOUT* wave, UINT device, const WAVEFORMATEX* format, 00538 DWORD callback, DWORD callbackData, DWORD flags)); 00539 _TX_DLLIMPORT ("WinMM", MMRESULT, waveOutPrepareHeader, (HWAVEOUT wave, WAVEHDR* header, UINT size)); 00540 _TX_DLLIMPORT ("WinMM", MMRESULT, waveOutUnprepareHeader, (HWAVEOUT wave, WAVEHDR* header, UINT size)); 00541 _TX_DLLIMPORT ("WinMM", MMRESULT, waveOutWrite, (HWAVEOUT wave, WAVEHDR* header, UINT size)); 00542 _TX_DLLIMPORT ("WinMM", MMRESULT, waveOutReset, (HWAVEOUT wave)); 00543 _TX_DLLIMPORT ("WinMM", MMRESULT, waveOutClose, (HWAVEOUT wave)); 00544 _TX_DLLIMPORT ("WinMM", MMRESULT, waveOutBreakLoop, (HWAVEOUT wave)); 00545 _TX_DLLIMPORT ("WinMM", MMRESULT, waveOutGetPosition, (HWAVEOUT wave, MMTIME* time, UINT size)); 00546 00547 _TX_DLLIMPORT ("WinMM", MMRESULT, waveInOpen, (HWAVEIN* wave, UINT device, const WAVEFORMATEX* format, 00548 DWORD callback, DWORD callbackData, DWORD flags)); 00549 _TX_DLLIMPORT ("WinMM", MMRESULT, waveInPrepareHeader, (HWAVEIN wave, WAVEHDR* header, UINT size)); 00550 _TX_DLLIMPORT ("WinMM", MMRESULT, waveInUnprepareHeader, (HWAVEIN wave, WAVEHDR* header, UINT size)); 00551 _TX_DLLIMPORT ("WinMM", MMRESULT, waveInAddBuffer, (HWAVEIN wave, WAVEHDR* header, UINT size)); 00552 _TX_DLLIMPORT ("WinMM", MMRESULT, waveInStart, (HWAVEIN wave)); 00553 _TX_DLLIMPORT ("WinMM", MMRESULT, waveInStop, (HWAVEIN wave)); 00554 _TX_DLLIMPORT ("WinMM", MMRESULT, waveInReset, (HWAVEIN wave)); 00555 _TX_DLLIMPORT ("WinMM", MMRESULT, waveInClose, (HWAVEIN wave)); 00556 _TX_DLLIMPORT ("WinMM", MMRESULT, waveInGetPosition, (HWAVEIN wave, MMTIME* time, UINT size)); 00557 } 00558 00559 //}================================================================================================================ 00560 00561 #if defined (_GCC_VER) && (_GCC_VER < 530) 00562 #pragma GCC system_header 00563 #endif 00564 00565 int _txWaveInit(); 00566 00567 int _txWaveInitialized = _txWaveInit(); 00568 00569 int _txWaveInit() 00570 { 00571 assert (sizeof (txWaveSample_t) == txWaveFormat.nBlockAlign); 00572 assert (txWaveFormat.nBlockAlign == txWaveFormat.wBitsPerSample/8 * txWaveFormat.nChannels); 00573 assert (txWaveFormat.nAvgBytesPerSec == txWaveFormat.nSamplesPerSec * txWaveFormat.nBlockAlign); 00574 00575 (void) _txWaveInitialized; 00576 return 1; 00577 } 00578 00579 //----------------------------------------------------------------------------------------------------------------- 00580 00581 HWAVEOUT txWaveOut (int timeMs /* = -INT_MAX */, 00582 double freqL /* = 0 */, double volL /* = 50 */, 00583 double freqR /* = -1 */, double volR /* = -1 */, 00584 int loops /* = 1 */, 00585 const txWaveData_t& data /* = txWaveData_t() */) 00586 { 00587 static HWAVEOUT waveOut = NULL; 00588 static WAVEHDR waveHdr[8] = {}; 00589 00590 static long long phase[2] = {}; 00591 00592 int time0 = GetTickCount(); 00593 00594 // Check the params 00595 00596 if (freqR < 0) freqR = freqL; 00597 if (volR < 0) volR = volL; 00598 00599 if (loops == 1) loops = 0; 00600 00601 // Initialize the wave device 00602 00603 if (!waveOut) 00604 { 00605 Win32::waveOutOpen (&waveOut, WAVE_MAPPER, &txWaveFormat, 0, 0, 0) == MMSYSERR_NOERROR asserted; 00606 if (!waveOut) return NULL; 00607 } 00608 00609 // Prepare and start the sound 00610 00611 if (timeMs && (freqL > 0 || freqR > 0 || data.size())) 00612 { 00613 // Prepare the WAVEHDR 00614 00615 WAVEHDR wav = {}; 00616 00617 unsigned size = (unsigned) data.size(); 00618 if ((freqL > 0 && volL > 0) || (freqR > 0 && volR > 0)) size = ROUND (abs (timeMs) * txWaveSampleRate); 00619 00620 wav.dwBufferLength = (unsigned) (size * sizeof (txWaveSample_t)); 00621 wav.lpData = (char*) malloc (wav.dwBufferLength); assert (wav.lpData); 00622 00623 wav.dwFlags = loops? (WHDR_BEGINLOOP | WHDR_ENDLOOP) : 0; 00624 wav.dwLoops = loops; 00625 00626 // Copy raw data 00627 00628 size_t szPrefill = MIN (size, data.size()) * sizeof (txWaveSample_t); 00629 00630 if (szPrefill) memcpy (wav.lpData, &data[0], szPrefill); 00631 00632 // Add harmonic data. All values premultiplied by 360 and converted to integers. 00633 00634 if (freqL > 0 || freqR > 0) 00635 { 00636 long long time = ROUND (360 * abs (timeMs) / 1000.0), 00637 freq[2] = { ROUND (360 * freqL), 00638 ROUND (360 * freqR) }, 00639 vol [2] = { ROUND (360 * volL / 101.0 * (int) txWaveVolMax), 00640 ROUND (360 * volR / 101.0 * (int) txWaveVolMax) }; 00641 00642 static const int sinTab[91] = { 0, 6, 13, 19, 25, 31, 38, 44, 50, 56, 00643 63, 69, 75, 81, 87, 93, 99, 105, 111, 117, 00644 123, 129, 135, 141, 146, 152, 158, 163, 169, 175, 00645 180, 185, 191, 196, 201, 206, 212, 217, 222, 227, 00646 231, 236, 241, 246, 250, 255, 259, 263, 268, 272, 00647 276, 280, 284, 288, 291, 295, 298, 302, 305, 309, 00648 312, 315, 318, 321, 324, 326, 329, 331, 334, 336, 00649 338, 340, 342, 344, 346, 348, 349, 351, 352, 353, 00650 355, 356, 356, 357, 358, 359, 359, 360, 360, 360, 360 }; 00651 00652 txWaveSample_t* buf = (txWaveSample_t*) wav.lpData; 00653 00654 #pragma GCC diagnostic ignored "-Wconversion" 00655 00656 #define MAKEDATA_(chan) \ 00657 { \ 00658 for (unsigned i = 0; i < size; i++) \ 00659 { \ 00660 int ch = (i < szPrefill)? buf[i].ch[chan] * 129600 : 0; \ 00661 \ 00662 int t = (phase[chan] + freq[chan] * time * i/size) / 360 % 360; \ 00663 \ 00664 int sign = +1; \ 00665 if (t >= 180) { t = t - 180; sign = -1; } \ 00666 if (t >= 90) { t = 180 - t; } \ 00667 \ 00668 assert (0 <= t && t < (int) sizearr (sinTab)); \ 00669 \ 00670 buf[i].ch[chan] = (short) ((ch + vol[chan] * sign * sinTab [t]) / 129600); \ 00671 } \ 00672 \ 00673 phase[chan] += freq[chan] * time; \ 00674 } 00675 00676 if (volL > 0 && freqL > 0) MAKEDATA_ (0); 00677 if (volR > 0 && freqR > 0) MAKEDATA_ (1); 00678 00679 #undef MAKEDATA_ 00680 #pragma GCC diagnostic warning "-Wconversion" 00681 } 00682 00683 // Find free WAVEHDR 00684 00685 WAVEHDR* next = NULL; 00686 00687 for (size_t i = 0; ; i = (i+1) % sizearr (waveHdr), Sleep (_txWindowUpdateInterval)) 00688 { 00689 if (Win32::waveOutUnprepareHeader (waveOut, &waveHdr[i], sizeof (WAVEHDR)) == MMSYSERR_NOERROR) 00690 { 00691 next = &waveHdr[i]; // Free WAVEHDR found 00692 FREE (next->lpData); 00693 break; 00694 } 00695 00696 if (timeMs < 0 && GetTickCount() - time0 < (unsigned) abs (timeMs)) 00697 break; 00698 } 00699 00700 // Start the sound 00701 00702 if (next) 00703 { 00704 std::swap (wav, *next); // Put the data prepared to queue 00705 00706 Win32::waveOutPrepareHeader (waveOut, next, sizeof (WAVEHDR)) == MMSYSERR_NOERROR asserted; 00707 Win32::waveOutWrite (waveOut, next, sizeof (WAVEHDR)) == MMSYSERR_NOERROR asserted; 00708 00709 Win32::waveOutBreakLoop (waveOut) == MMSYSERR_NOERROR asserted; 00710 } 00711 } 00712 00713 // Wait and stop the sound 00714 00715 if (timeMs <= 0) 00716 { 00717 if (!timeMs) Win32::waveOutReset (waveOut) == MMSYSERR_NOERROR asserted; // Immediate stop 00718 00719 // Wait for sound to stop 00720 00721 for (size_t i = 0; i < sizearr (waveHdr); i++, Sleep (_txWindowUpdateInterval)) 00722 { 00723 if (GetTickCount() - time0 >= (unsigned) abs (timeMs)) break; 00724 00725 if ((waveHdr[i].dwFlags & WHDR_PREPARED) && !(waveHdr[i].dwFlags & WHDR_DONE)) { i--; continue; } 00726 } 00727 00728 Win32::waveOutReset (waveOut) == MMSYSERR_NOERROR asserted; 00729 00730 // Free the buffers 00731 00732 for (size_t i = 0; i < sizearr (waveHdr); i++) 00733 { 00734 Win32::waveOutUnprepareHeader (waveOut, &waveHdr[i], sizeof (WAVEHDR)); 00735 FREE (waveHdr[i].lpData); 00736 } 00737 00738 // Close the wave device 00739 00740 Win32::waveOutClose (waveOut) == MMSYSERR_NOERROR asserted; 00741 waveOut = NULL; 00742 } 00743 00744 return waveOut; 00745 } 00746 00747 //----------------------------------------------------------------------------------------------------------------- 00748 00749 HWAVEOUT txWaveOut (const txWaveData_t& data, int loops /* = 1 */) 00750 { 00751 return txWaveOut (-INT_MAX, 0,0,0,0, loops, data); 00752 } 00753 00754 //----------------------------------------------------------------------------------------------------------------- 00755 00756 txWaveData_t txWaveIn (int timeMs, 00757 MonitorProc_t monitorProc /* = NULL */, void* userData /* = NULL */, 00758 unsigned frameTime /* = 0 */) 00759 { 00760 static HWAVEIN waveIn = NULL; 00761 static WAVEHDR waveHdr[2] = {}; 00762 00763 txWaveData_t data; 00764 00765 int time0 = GetTickCount(); 00766 00767 // Initialize the wave device 00768 00769 if (!waveIn) 00770 { 00771 Win32::waveInOpen (&waveIn, WAVE_MAPPER, &txWaveFormat, 0, 0, 0) == MMSYSERR_NOERROR asserted; 00772 if (!waveIn) return data; 00773 } 00774 00775 // Calculate the sizes 00776 00777 if (!frameTime) frameTime = 100; // Default frame time 00778 00779 unsigned size = ROUND (abs (timeMs) * txWaveSampleRate); 00780 unsigned frame = ROUND (frameTime * txWaveSampleRate); 00781 00782 // Feed the recording queue with buffers 00783 00784 for (unsigned i = 0; i < sizearr (waveHdr); i++) 00785 { 00786 waveHdr[i].dwBufferLength = frame * (unsigned) sizeof (txWaveSample_t); 00787 waveHdr[i].lpData = (char*) malloc (waveHdr[i].dwBufferLength); assert (waveHdr[i].lpData); 00788 00789 Win32::waveInPrepareHeader (waveIn, &waveHdr[i], sizeof (waveHdr[i])) == MMSYSERR_NOERROR asserted; 00790 Win32::waveInAddBuffer (waveIn, &waveHdr[i], sizeof (waveHdr[i])) == MMSYSERR_NOERROR asserted; 00791 } 00792 00793 // Start the recording 00794 00795 data.resize (size); 00796 txWaveData_t (data) .swap (data); // C++11: data.shrink_to_fit(); 00797 data.resize (0); 00798 00799 Win32::waveInStart (waveIn) == MMSYSERR_NOERROR asserted; 00800 00801 // Recording loop 00802 00803 for (size_t i = 0; ; i = (i+1) % sizearr (waveHdr), Sleep (_txWindowUpdateInterval)) 00804 { 00805 WAVEHDR* wav = &waveHdr[i]; 00806 00807 if (!(wav->dwFlags & WHDR_DONE)) continue; // Buffer is not done yet 00808 00809 // Process the buffer recorded 00810 00811 size_t pos = data.size(); 00812 data.resize (pos + MIN (wav->dwBytesRecorded / sizeof (txWaveSample_t), size - pos)); 00813 00814 memcpy (&data[0] + pos, wav->lpData, (data.size() - pos) * sizeof (txWaveSample_t)); 00815 00816 if (monitorProc && !monitorProc (waveIn, data, userData)) break; // Monitor breaks the recording 00817 00818 if (timeMs < 0 && GetTickCount() - time0 >= (unsigned) abs (timeMs)) break; // Time is over 00819 00820 if (data.size() == size) break; // All data recorded 00821 00822 // Re-feed the queue with the buffer 00823 00824 wav->dwFlags = 0; 00825 wav->dwBytesRecorded = 0; 00826 00827 Win32::waveInPrepareHeader (waveIn, wav, sizeof (*wav)) == MMSYSERR_NOERROR asserted; 00828 Win32::waveInAddBuffer (waveIn, wav, sizeof (*wav)) == MMSYSERR_NOERROR asserted; 00829 } 00830 00831 // Stop the recording 00832 00833 Win32::waveInStop (waveIn) == MMSYSERR_NOERROR asserted; 00834 Win32::waveInReset (waveIn) == MMSYSERR_NOERROR asserted; 00835 00836 // Free the buffers 00837 00838 for (unsigned i = 0; i < sizearr (waveHdr); i++) 00839 { 00840 Win32::waveInUnprepareHeader (waveIn, &waveHdr[i], sizeof (waveHdr[i])) == MMSYSERR_NOERROR asserted; 00841 FREE (waveHdr[i].lpData); 00842 } 00843 00844 // Close the wave device 00845 00846 Win32::waveInClose (waveIn) == MMSYSERR_NOERROR asserted; 00847 waveIn = NULL; 00848 00849 return data; 00850 } 00851 00852 //----------------------------------------------------------------------------------------------------------------- 00853 00854 unsigned long txWaveGetPosition (void* wave) 00855 { 00856 static MMTIME time = { TIME_SAMPLES }; 00857 00858 if (Win32::waveOutGetPosition ((HWAVEOUT) wave, &time, sizeof (time)) == MMSYSERR_NOERROR) return (long) time.u.sample; 00859 if (Win32::waveInGetPosition ((HWAVEIN) wave, &time, sizeof (time)) == MMSYSERR_NOERROR) return (long) time.u.sample; 00860 00861 return ULONG_MAX; 00862 } 00863 00864 //----------------------------------------------------------------------------------------------------------------- 00865 00866 struct WAVFILEHEADER 00867 { 00868 unsigned chunkId; // 0x46464952 'RIFF' 00869 unsigned long chunkSize; // FileSize - sizeof (chunkId) - sizeof (chunkSize) 00870 unsigned format; // 0x45564157 'WAVE' 00871 00872 unsigned subchunk1Id; // 0x20746d66 'fmt ' 00873 unsigned long subchunk1Size; // sizeof (PCMWAVEFORMAT), maybe +2, see below 00874 00875 PCMWAVEFORMAT pcm; 00876 00877 /* // Here lies metadata, we ignore them 00878 00879 struct // If (subchunk1Size == sizeof (PCMWAVEFORMAT) + 2) 00880 { 00881 unsigned short size; 00882 unsigned char data[]; // data [size] 00883 } 00884 metadata[]; 00885 00886 */ 00887 00888 unsigned subchunk2Id; // 0x61746164 'data' 00889 unsigned long subchunk2Size; // length (numSamples * pcm.wf.nChannels * pcm.wBitsPerSample/8 00890 00891 txWaveSample_t data[]; // data [numSamples], size in bytes = subchunk2Size 00892 }; 00893 00894 //----------------------------------------------------------------------------------------------------------------- 00895 00896 #define TRY int __error = 0; 00897 #define FAIL(err) { __error = (err); goto __catch; } 00898 #define FAILURE FAIL (__LINE__) 00899 #define CATCH __catch: if (__error) 00900 00901 //----------------------------------------------------------------------------------------------------------------- 00902 00903 txWaveData_t txWaveLoadWav (const char filename[]) 00904 { 00905 assert (filename); 00906 00907 FILE* f = NULL; 00908 txWaveData_t data; 00909 00910 TRY 00911 { 00912 // Open the file 00913 00914 fopen_s (&f, filename, "rb"); 00915 if (!f) FAILURE; 00916 00917 long size = _filelength (_fileno (f)); 00918 00919 // Allocate memory for waveform data 00920 00921 try { data.resize (size / sizeof (txWaveSample_t)); } 00922 catch (...) { FAILURE; } 00923 00924 // Read the file header 00925 00926 WAVFILEHEADER* wav = (WAVFILEHEADER*) &data[0]; 00927 fread (wav, sizeof (WAVFILEHEADER), 1, f) == 1 asserted; 00928 00929 // Check file format and properties 00930 00931 if (wav->chunkId != 0x46464952 /* 'RIFF' */) FAILURE; 00932 if (wav->format != 0x45564157 /* 'WAVE' */) FAILURE; 00933 if (wav->subchunk1Id != 0x20746d66 /* 'fmt ' */) FAILURE; 00934 00935 if (wav->pcm.wf.wFormatTag != txWaveFormat.wFormatTag) FAILURE; 00936 if (wav->pcm.wf.nChannels != txWaveFormat.nChannels) FAILURE; 00937 if (wav->pcm.wf.nSamplesPerSec != txWaveFormat.nSamplesPerSec) FAILURE; 00938 if (wav->pcm.wf.nAvgBytesPerSec != txWaveFormat.nAvgBytesPerSec) FAILURE; 00939 if (wav->pcm.wf.nBlockAlign != txWaveFormat.nBlockAlign) FAILURE; 00940 00941 if (wav->pcm.wBitsPerSample != txWaveFormat.wBitsPerSample) FAILURE; 00942 00943 // Skip metadata 00944 00945 unsigned metaSize = (wav->subchunk1Size == sizeof (PCMWAVEFORMAT) + 2)? *(short*)&wav->subchunk2Id : 0; 00946 fread (&wav->subchunk2Id, 1, metaSize, f) == metaSize asserted; 00947 00948 // Now we at waveform data section 00949 00950 if (wav->subchunk2Id != 0x61746164 /* 'data' */) FAILURE; 00951 00952 // Read the waveform data 00953 00954 size -= (long) sizeof (WAVFILEHEADER) + metaSize; 00955 fread (wav, size, 1, f) == 1 asserted; 00956 00957 // Adjust vector size according to the data read 00958 00959 data.resize (size / sizeof (txWaveSample_t)); 00960 } 00961 00962 CATCH 00963 { 00964 txNotifyIcon (NIIF_ERROR, "txWaveLoadWav() сообщает", "\nОшибка чтения WAV-файла \"%s\"\n\n" 00965 "См. %s, строку %d", filename, __FILE__, __error); 00966 } 00967 00968 if (f) fclose (f) == 0 asserted; 00969 00970 return data; 00971 } 00972 00973 //----------------------------------------------------------------------------------------------------------------- 00974 00975 bool txWaveSaveWav (const txWaveData_t& data, const char filename[]) 00976 { 00977 assert (filename); 00978 00979 unsigned size = (unsigned) (data.size() * sizeof (txWaveSample_t)); 00980 00981 WAVFILEHEADER header = { 0x46464952 /* 'RIFF' */, 00982 (unsigned) (sizeof (header) + size - sizeof (header.chunkId) - sizeof (header.chunkSize)), 00983 0x45564157 /* 'WAVE' */, 00984 00985 0x20746d66 /* 'fmt ' */, 00986 sizeof (PCMWAVEFORMAT), 00987 00988 {{txWaveFormat.wFormatTag, txWaveFormat.nChannels, 00989 txWaveFormat.nSamplesPerSec, txWaveFormat.nAvgBytesPerSec, 00990 txWaveFormat.nBlockAlign}, txWaveFormat.wBitsPerSample}, 00991 00992 // Here should be metadata, we live happy without them 00993 00994 0x61746164 /* 'data' */, 00995 size 00996 }; 00997 00998 FILE* f = NULL; 00999 fopen_s (&f, filename, "wb"); 01000 if (!f) return false; 01001 01002 fwrite (&header, sizeof (header), 1, f) == 1 asserted; 01003 fwrite (&data[0], size, 1, f) == 1 asserted; 01004 01005 fclose (f) == 0 asserted; 01006 01007 return true; 01008 } 01009 01010 //----------------------------------------------------------------------------------------------------------------- 01011 01012 #endif 01013 01016 _TX_END_NAMESPACE 01017 01020 //================================================================================================================= 01021 01022 #if defined (_MSC_VER) 01023 #pragma warning (pop) 01024 #endif 01025 01026 //================================================================================================================= 01027 01028 #endif // __TXWAVE_INCLUDED