Changeset 2778:f7b661680b55 in roaraudio
- Timestamp:
- 09/24/09 02:11:34 (15 years ago)
- Branch:
- default
- Phase:
- public
- Location:
- roard
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
roard/driver_wmm.c
r2775 r2778 27 27 #if defined(ROAR_HAVE_H_MMSYSTEM) && defined(ROAR_TARGET_WIN32) 28 28 29 static int _alloc_wave_headers(struct driver_wmm * self) { 30 int bytesPerBlock = self->wavefmt.nBlockAlign * self->splPerBlock; 31 /* int bytes = internal->blocks * (sizeof(WAVEHDR) + bytesPerBlock); */ 32 int bytes = self->blocks * (sizeof(*self->wh) + bytesPerBlock); 33 int res; 34 MMRESULT mmres; 35 36 self->bigbuffer = malloc(bytes); 37 if (self->bigbuffer != NULL) { 38 int i; 39 BYTE * b; 40 41 memset(self->bigbuffer,0,bytes); 42 self->wh = self->bigbuffer; 43 self->spl = (LPBYTE) (self->wh+self->blocks); 44 for (i=0, b=self->spl; i<self->blocks; ++i, b+=bytesPerBlock) { 45 self->wh[i].data = b; 46 self->wh[i].wh.lpData = self->wh[i].data; 47 self->wh[i].length = bytesPerBlock; 48 self->wh[i].wh.dwBufferLength = self->wh[i].length; 49 self->wh[i].wh.dwUser = (DWORD_PTR)self; 50 mmres = waveOutPrepareHeader(self->hwo, 51 &self->wh[i].wh,sizeof(WAVEHDR)); 52 if (MMSYSERR_NOERROR != mmres) { 53 break; 54 } 55 } 56 if (i<self->blocks) { 57 while (--i >= 0) { 58 waveOutUnprepareHeader(self->hwo, 59 &self->wh[i].wh,sizeof(WAVEHDR)); 60 } 61 free(self->bigbuffer); 62 self->wh = 0; 63 self->spl = 0; 64 self->bigbuffer = 0; 65 } else { 66 /* all ok ! */ 67 } 68 } 69 70 res = (self->bigbuffer != NULL); 71 return res; 72 } 73 74 static int _get_free_block(struct driver_wmm * self); 75 static int _wait_wave_headers(struct driver_wmm * self, int wait_all) { 76 int res = 1; 77 78 while (self->sent_blocks > 0) { 79 int n; 80 _get_free_block(self); 81 n = self->sent_blocks; 82 if (n > 0) { 83 unsigned int ms = (self->msPerBlock>>1)+1; 84 if (wait_all) ms *= n; 85 Sleep(ms); 86 } 87 } 88 89 res &= !self->sent_blocks; 90 return res; 91 } 92 93 static int _get_free_block(struct driver_wmm * self) { 94 const int idx = self->widx; 95 int ridx = self->ridx; 96 97 while (self->wh[ridx].sent && !!(self->wh[ridx].wh.dwFlags & WHDR_DONE)) { 98 /* block successfully sent to hardware, release it */ 99 /*debug("_ao_get_free_block: release block %d\n",ridx);*/ 100 self->wh[ridx].sent = 0; 101 self->wh[ridx].wh.dwFlags &= ~WHDR_DONE; 102 103 --self->full_blocks; 104 if (self->full_blocks<0) { 105 self->full_blocks = 0; 106 } 107 108 --self->sent_blocks; 109 if (self->sent_blocks<0) { 110 self->sent_blocks = 0; 111 } 112 if (++ridx >= self->blocks) ridx = 0; 113 } 114 self->ridx = ridx; 115 116 return self->wh[idx].sent 117 ? -1 118 : idx; 119 } 120 121 static int _free_wave_headers(struct driver_wmm * self) { 122 MMRESULT mmres; 123 int res = 1; 124 125 if (self->wh) { 126 int i; 127 128 /* Reset so we dont need to wait ... Just a satefy net 129 * since _ao_wait_wave_headers() has been called once before. 130 */ 131 mmres = waveOutReset(self->hwo); 132 /* Wait again to be sure reseted waveheaders has been released. */ 133 _wait_wave_headers(self, 0); 134 135 for (i=self->blocks; --i>=0; ) { 136 mmres = waveOutUnprepareHeader(self->hwo, 137 &self->wh[i].wh,sizeof(WAVEHDR)); 138 139 res &= mmres == MMSYSERR_NOERROR; 140 } 141 self->wh = 0; 142 self->spl = 0; 143 } 144 145 return res; 146 } 147 148 /* Send a block to audio hardware */ 149 static int _send_block(struct driver_wmm * self, const int idx) { 150 MMRESULT mmres; 151 152 /* Satanity checks */ 153 if (self->wh[idx].sent) { 154 return 0; 155 } 156 if (!!(self->wh[idx].wh.dwFlags & WHDR_DONE)) { 157 return 0; 158 } 159 160 /* count <= 0, just pretend it's been sent */ 161 if (self->wh[idx].count <= 0) { 162 self->wh[idx].sent = 2; /* set with 2 so we can track these special cases */ 163 self->wh[idx].wh.dwFlags |= WHDR_DONE; 164 ++self->sent_blocks; 165 return 1; 166 } 167 168 self->wh[idx].wh.dwBufferLength = self->wh[idx].count; 169 self->wh[idx].count = 0; 170 mmres = waveOutWrite(self->hwo, 171 &self->wh[idx].wh, sizeof(WAVEHDR)); 172 self->wh[idx].sent = (mmres == MMSYSERR_NOERROR); 173 /*&& !(internal->wh[idx].wh.dwFlags & WHDR_DONE);*/ 174 self->sent_blocks += self->wh[idx].sent; 175 return mmres == MMSYSERR_NOERROR; 176 } 177 29 178 int driver_wmm_open_vio(struct roar_vio_calls * inst, char * device, struct roar_audio_info * info, int fh, struct roar_stream_server * sstream) { 30 179 struct driver_wmm * self; 31 180 WAVEFORMATEX wavefmt; 181 MMRESULT mmres; 32 182 33 183 if ( (self = malloc(sizeof(struct driver_wmm))) == NULL ) … … 45 195 memset(&wavefmt, 0, sizeof(wavefmt)); 46 196 47 wavefmt.wFormatTag = WAVE_FORMAT_PCM;48 wavefmt.nChannels = info->channels;49 wavefmt.wBitsPerSample = info->bits;50 wavefmt.nSamplesPerSec = info->rate;51 wavefmt.nBlockAlign = (wavefmt.wBitsPerSample>>3)*wavefmt.nChannels;52 wavefmt.nAvgBytesPerSec = wavefmt.nSamplesPerSec*wavefmt.nBlockAlign;53 wavefmt.cbSize = 0;197 self->wavefmt.wFormatTag = WAVE_FORMAT_PCM; 198 self->wavefmt.nChannels = info->channels; 199 self->wavefmt.wBitsPerSample = info->bits; 200 self->wavefmt.nSamplesPerSec = info->rate; 201 self->wavefmt.nBlockAlign = (self->wavefmt.wBitsPerSample>>3)*self->wavefmt.nChannels; 202 self->wavefmt.nAvgBytesPerSec = self->wavefmt.nSamplesPerSec*self->wavefmt.nBlockAlign; 203 self->wavefmt.cbSize = 0; 54 204 55 205 /* $$$ later this should be optionnal parms */ 206 self->id = WAVE_MAPPER; 56 207 self->blocks = 64; 57 208 self->splPerBlock = 512; … … 59 210 (self->splPerBlock * 1000 + info->rate - 1) / info->rate; 60 211 212 mmres = 213 waveOutOpen(&self->hwo, 214 self->id, 215 &self->wavefmt, 216 (DWORD_PTR)0/* waveOutProc */, 217 (DWORD_PTR)self, 218 CALLBACK_NULL/* |WAVE_FORMAT_DIRECT */|WAVE_ALLOWSYNC); 219 if ( mmres != MMSYSERR_NOERROR ) { 220 driver_wmm_close_vio(inst); 221 return -1; 222 } 223 224 // FIXME: do error checking 225 waveOutGetID(self->hwo, &(self->id)); 226 227 _alloc_wave_headers(self); 228 229 self->opened = 1; 230 61 231 return 0; 62 232 } … … 71 241 return -1; 72 242 243 if ( self->opened ) { 244 _wait_wave_headers(self, 1); 245 _free_wave_headers(self); 246 waveOutClose(self->hwo); 247 } 248 73 249 free(self); 74 250 … … 77 253 78 254 ssize_t driver_wmm_write(struct roar_vio_calls * vio, void *buf, size_t count) { 79 return -1; 255 struct driver_wmm * self; 256 int ret = 1; 257 258 if ( vio == NULL ) 259 return -1; 260 261 if ( (self = vio->inst) == NULL ) 262 return -1; 263 264 if ( ! self->opened ) 265 return -1; 266 267 while(ret && count > 0) { 268 int n; 269 const int idx = _get_free_block(self); 270 271 if (idx == -1) { 272 /* debug("sleep %dms, rem %d bytes\n",internal->msPerBlock,num_bytes); */ 273 Sleep(self->msPerBlock); 274 continue; 275 } 276 277 /* Get free bytes in the block */ 278 n = self->wh[idx].wh.dwBufferLength 279 - self->wh[idx].count; 280 281 /* debug("free in block %d : %d/%d\n", */ 282 /* idx,n,internal->wh[idx].dwBufferLength); */ 283 284 /* Get amount to copy */ 285 if (n > (int)count) { 286 n = count; 287 } 288 /* debug("copy = %d\n",n); */ 289 290 291 292 /* Do copy */ 293 CopyMemory((char*)self->wh[idx].wh.lpData 294 + self->wh[idx].count, 295 buf, n); 296 297 /* Updates pointers and counters */ 298 buf += n; 299 count -= n; 300 /* debug("rem = %d\n",num_bytes); */ 301 self->wh[idx].count += n; 302 303 /* Is this block full ? */ 304 if (self->wh[idx].count 305 == self->wh[idx].wh.dwBufferLength) { 306 ++self->full_blocks; 307 /* debug("blocks %d full, total:%d\n",internal->widx,internal->full_blocks); */ 308 if (++self->widx == self->blocks) { 309 self->widx = 0; 310 } 311 ret = _send_block(self, idx); 312 } 313 } 314 315 /* debug("ao_wmm_play => %d rem => [%s]\n",num_bytes,ret?"success":"error"); */ 316 return ret > -1 ? count : -1; 80 317 } 81 318 -
roard/include/driver_wmm.h
r2774 r2778 40 40 int msPerBlock; /* millisecond per block (approx.) */ 41 41 42 // void * bigbuffer; /* Allocated buffer for waveheaders and sound data */ 43 // myWH_t * wh; /* Pointer to waveheaders in bigbuffer */ 44 // BYTE * spl; /* Pointer to sound data in bigbuffer */ 42 void * bigbuffer; /* Allocated buffer for waveheaders and sound data */ 43 struct { 44 WAVEHDR wh; /* waveheader */ 45 char * data; /* sample data ptr */ 46 int idx; /* index of this header */ 47 int count; /* current byte count */ 48 int length; /* size of data */ 49 int sent; /* set when header is sent to device */ 50 } * wh; /* Pointer to waveheaders in bigbuffer */ 51 BYTE * spl; /* Pointer to sound data in bigbuffer */ 52 53 int sent_blocks; /* Number of waveheader sent (not ack). */ 54 int full_blocks; /* Number of waveheader full (ready to send). */ 55 int widx; /* Index to the block being currently filled. */ 56 int ridx; /* Index to the block being sent. */ 45 57 }; 46 58
Note: See TracChangeset
for help on using the changeset viewer.