- Timestamp:
- Sep 9, 2010 11:01:38 AM (14 years ago)
- Location:
- trunk/src/VBox/Devices/Audio
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/audio.c
r29250 r32337 143 143 }, 144 144 145 { 100 }, /* period*/145 { 200 }, /* frequency (in Hz) */ 146 146 0, /* plive */ 147 147 }; … … 1526 1526 1527 1527 /* Misc */ 1528 {"TIMER_ PERIOD", AUD_OPT_INT, &conf.period.hz,1529 "Timer period in HZ(0 - use lowest possible)", NULL, 0},1528 {"TIMER_FREQ", AUD_OPT_INT, &conf.period.hz, 1529 "Timer frequency in Hz (0 - use lowest possible)", NULL, 0}, 1530 1530 1531 1531 {"PLIVE", AUD_OPT_BOOL, &conf.plive, -
trunk/src/VBox/Devices/Audio/audiosniffer.c
r28800 r32337 26 26 #include <iprt/string.h> 27 27 #include <iprt/alloc.h> 28 #include <iprt/file.h> 28 29 29 30 #include "Builtins.h" … … 54 55 PPDMIAUDIOSNIFFERCONNECTOR pDrv; 55 56 57 void *pCapFileCtx; 56 58 } AUDIOSNIFFERSTATE; 57 59 58 60 static AUDIOSNIFFERSTATE *g_pData = NULL; 61 62 typedef struct { 63 RTFILE capFile; 64 int curSampPerSec; 65 int curBitsPerSmp; 66 int curChannels; 67 uint64_t lastChunk; 68 } AUDCAPSTATE; 69 70 typedef struct { 71 uint16_t wFormatTag; 72 uint16_t nChannels; 73 uint32_t nSamplesPerSec; 74 uint32_t nAvgBytesPerSec; 75 uint16_t nBlockAlign; 76 uint16_t wBitsPerSample; 77 } WAVEFMTHDR; 78 79 static update_prev_chunk(AUDCAPSTATE *pState) 80 { 81 size_t written; 82 uint64_t cur_ofs; 83 uint64_t new_ofs; 84 uint32_t chunk_len; 85 86 Assert(pState); 87 /* Write the size of the previous data chunk, if there was one. */ 88 if (pState->lastChunk) 89 { 90 cur_ofs = RTFileTell(pState->capFile); 91 chunk_len = cur_ofs - pState->lastChunk - sizeof(chunk_len); 92 RTFileWriteAt(pState->capFile, pState->lastChunk, &chunk_len, sizeof(chunk_len), &written); 93 RTFileSeek(pState->capFile, 0, RTFILE_SEEK_END, &new_ofs); 94 } 95 } 96 97 static int create_capture_file(AUDCAPSTATE *pState, const char *fname) 98 { 99 int rc; 100 size_t written; 101 102 Assert(pState); 103 memset(pState, 0, sizeof(*pState)); 104 /* Create the file and write the RIFF header. */ 105 rc = RTFileOpen(&pState->capFile, fname, 106 RTFILE_O_WRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_WRITE); 107 rc = RTFileWrite(pState->capFile, "RIFFxxxx", 8, &written); 108 return rc; 109 } 110 111 static int close_capture_file(AUDCAPSTATE *pState) 112 { 113 int rc; 114 size_t written; 115 uint64_t cur_ofs; 116 uint32_t riff_len; 117 118 Assert(pState); 119 update_prev_chunk(pState); 120 121 /* Update the global RIFF header. */ 122 cur_ofs = RTFileTell(pState->capFile); 123 riff_len = cur_ofs - 8; 124 RTFileWriteAt(pState->capFile, 4, &riff_len, sizeof(riff_len), &written); 125 126 rc = RTFileClose(pState->capFile); 127 return rc; 128 } 129 130 static inline int16_t clip_natural_int16_t(int64_t v) 131 { 132 if (v >= 0x7f000000) { 133 return 0x7fff; 134 } 135 else if (v < -2147483648LL) { 136 return (-32767-1); 137 } 138 return ((int16_t) (v >> (32 - 16))); 139 } 140 141 static int update_capture_file(AUDCAPSTATE *pState, HWVoiceOut *hw, st_sample_t *pSamples, unsigned cSamples) 142 { 143 size_t written; 144 uint16_t buff[16384]; 145 unsigned i; 146 uint16_t *dst_smp; 147 148 Assert(pState); 149 /* If the audio format changed, start a new WAVE chunk. */ 150 if ( hw->info.freq != pState->curSampPerSec 151 || hw->info.bits != pState->curBitsPerSmp 152 || hw->info.nchannels != pState->curChannels) 153 { 154 WAVEFMTHDR wave_hdr; 155 uint32_t chunk_len; 156 157 update_prev_chunk(pState); 158 159 /* Build a new format ('fmt ') chunk. */ 160 wave_hdr.wFormatTag = 1; /* Linear PCM */ 161 wave_hdr.nChannels = hw->info.nchannels; 162 wave_hdr.nSamplesPerSec = hw->info.freq; 163 wave_hdr.nAvgBytesPerSec = hw->info.bytes_per_second; 164 wave_hdr.nBlockAlign = 4; 165 wave_hdr.wBitsPerSample = hw->info.bits; 166 167 pState->curSampPerSec = hw->info.freq; 168 pState->curBitsPerSmp = hw->info.bits; 169 pState->curChannels = hw->info.nchannels; 170 171 /* Write the header to file. */ 172 RTFileWrite(pState->capFile, "WAVEfmt ", 8, &written); 173 chunk_len = sizeof(wave_hdr); 174 RTFileWrite(pState->capFile, &chunk_len, sizeof(chunk_len), &written); 175 RTFileWrite(pState->capFile, &wave_hdr, sizeof(wave_hdr), &written); 176 /* Write data chunk marker with dummy length. */ 177 RTFileWrite(pState->capFile, "dataxxxx", 8, &written); 178 pState->lastChunk = RTFileTell(pState->capFile) - 4; 179 } 180 181 /* Convert the samples from internal format. */ 182 //@todo: use mixer engine helpers instead? 183 for (i = 0, dst_smp = buff; i < cSamples; ++i) 184 { 185 *dst_smp++ = clip_natural_int16_t(pSamples->l); 186 *dst_smp++ = clip_natural_int16_t(pSamples->r); 187 ++pSamples; 188 } 189 190 // LogRel(("Audio: captured %d samples\n", cSamples)); 191 /* Write the audio data. */ 192 RTFileWrite(pState->capFile, buff, cSamples * (hw->info.bits / 8) * hw->info.nchannels, &written); 193 return VINF_SUCCESS; 194 } 59 195 60 196 /* … … 82 218 bool fUnsigned; 83 219 220 if (g_pData) 221 update_capture_file(g_pData->pCapFileCtx, hw, pvSamples, cSamples); 222 84 223 if (!g_pData || !g_pData->pDrv || !g_pData->fEnabled) 85 224 { … … 137 276 static DECLCALLBACK(int) audioSnifferR3Destruct(PPDMDEVINS pDevIns) 138 277 { 278 AUDIOSNIFFERSTATE *pThis = PDMINS_2_DATA(pDevIns, AUDIOSNIFFERSTATE *); 139 279 PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns); 280 281 close_capture_file(pThis->pCapFileCtx); 282 RTMemFree(pThis->pCapFileCtx); 140 283 141 284 /* Zero the global pointer. */ … … 211 354 g_pData = pThis; 212 355 } 356 357 pThis->pCapFileCtx = RTMemAlloc(sizeof(AUDCAPSTATE)); 358 create_capture_file(pThis->pCapFileCtx, "c:\\vbox.wav"); 213 359 214 360 return rc;
Note:
See TracChangeset
for help on using the changeset viewer.