Changeset 32339 in vbox
- Timestamp:
- Sep 9, 2010 11:18:59 AM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/audiosniffer.c
r32337 r32339 26 26 #include <iprt/string.h> 27 27 #include <iprt/alloc.h> 28 #include <iprt/file.h>29 28 30 29 #include "Builtins.h" … … 55 54 PPDMIAUDIOSNIFFERCONNECTOR pDrv; 56 55 57 void *pCapFileCtx;58 56 } AUDIOSNIFFERSTATE; 59 57 60 58 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->curSampPerSec151 || hw->info.bits != pState->curBitsPerSmp152 || 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 }195 59 196 60 /* … … 218 82 bool fUnsigned; 219 83 220 if (g_pData)221 update_capture_file(g_pData->pCapFileCtx, hw, pvSamples, cSamples);222 223 84 if (!g_pData || !g_pData->pDrv || !g_pData->fEnabled) 224 85 { … … 276 137 static DECLCALLBACK(int) audioSnifferR3Destruct(PPDMDEVINS pDevIns) 277 138 { 278 AUDIOSNIFFERSTATE *pThis = PDMINS_2_DATA(pDevIns, AUDIOSNIFFERSTATE *);279 139 PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns); 280 281 close_capture_file(pThis->pCapFileCtx);282 RTMemFree(pThis->pCapFileCtx);283 140 284 141 /* Zero the global pointer. */ … … 354 211 g_pData = pThis; 355 212 } 356 357 pThis->pCapFileCtx = RTMemAlloc(sizeof(AUDCAPSTATE));358 create_capture_file(pThis->pCapFileCtx, "c:\\vbox.wav");359 213 360 214 return rc;
Note:
See TracChangeset
for help on using the changeset viewer.