src/audio/SDL_audio.c
branchgsoc2008_audio_resampling
changeset 2667 4174e511655f
parent 2666 e12ccc6c9576
equal deleted inserted replaced
2666:e12ccc6c9576 2667:4174e511655f
   317     Uint8 *stream;
   317     Uint8 *stream;
   318     int stream_len;
   318     int stream_len;
   319     void *udata;
   319     void *udata;
   320     void (SDLCALL * fill) (void *userdata, Uint8 * stream, int len);
   320     void (SDLCALL * fill) (void *userdata, Uint8 * stream, int len);
   321     int silence;
   321     int silence;
       
   322 	int stream_max_len;
   322 	
   323 	
   323 	/* For streaming when the buffer sizes don't match up */
   324 	/* For streaming when the buffer sizes don't match up */
   324 	Uint8 *istream;
   325 	Uint8 *istream;
   325 	int istream_len;
   326 	int istream_len;
   326 
   327 
   329     current_audio.impl.ThreadInit(device);
   330     current_audio.impl.ThreadInit(device);
   330 
   331 
   331     /* Set up the mixing function */
   332     /* Set up the mixing function */
   332     fill = device->spec.callback;
   333     fill = device->spec.callback;
   333     udata = device->spec.userdata;
   334     udata = device->spec.userdata;
       
   335 
       
   336 	/* By default do not stream */
       
   337 	device->use_streamer = 0;
   334 
   338 
   335     if (device->convert.needed) {
   339     if (device->convert.needed) {
   336         if (device->convert.src_format == AUDIO_U8) {
   340         if (device->convert.src_format == AUDIO_U8) {
   337             silence = 0x80;
   341             silence = 0x80;
   338         } else {
   342         } else {
   339             silence = 0;
   343             silence = 0;
   340         }
   344         }
   341         stream_len = device->convert.len;
   345 		
       
   346 		/* If the result of the conversion alters the length, i.e. resampling is being used, use the streamer */
       
   347 		if(device->convert.len_mult != 1 || device->convert.len_div != 1) {
       
   348 			/* The streamer's maximum length should be twice whichever is larger: spec.size or len_cvt */
       
   349 			stream_max_len = 2 * device->spec.size;
       
   350 			if(device->convert.len_mult > device->convert.len_div) {
       
   351 				stream_max_len *= device->convert.len_mult;
       
   352 				stream_max_len /= device->convert.len_div;
       
   353 			}
       
   354 			if(SDL_StreamInit(&device->streamer, stream_max_len, silence) < 0) return -1;
       
   355 			device->use_streamer = 1;
       
   356 			
       
   357 			/* istream_len should be the length of what we grab from the callback and feed to conversion,
       
   358 			    so that we get close to spec_size. I.e. we want device.spec_size = istream_len * u / d
       
   359 			*/
       
   360 			istream_len = device->spec.size * device->convert.len_div / device->convert.len_mult;
       
   361 		}
       
   362 		
       
   363         /* stream_len = device->convert.len; */
       
   364 		stream_len = device->spec.size;
   342     } else {
   365     } else {
   343         silence = device->spec.silence;
   366         silence = device->spec.silence;
   344         stream_len = device->spec.size;
   367         stream_len = device->spec.size;
   345     }
   368     }
   346 	
   369 	
   347 	/* Determine if the streamer is necessary here */
   370 	/* Determine if the streamer is necessary here */
   348 	if(device->use_streamer) {
   371 	if(device->use_streamer == 1) {
   349 		/* This code is almost the same as the old code. The difference is, instead of reding
   372 		/* This code is almost the same as the old code. The difference is, instead of reding
   350 		   directly from the callback into "stream", then converting and sending the audio off,
   373 		   directly from the callback into "stream", then converting and sending the audio off,
   351 		   we go: callback -> "istream" -> (conversion) -> streamer -> stream -> device.
   374 		   we go: callback -> "istream" -> (conversion) -> streamer -> stream -> device.
   352 		   However, reading and writing with streamer are done separately:
   375 		   However, reading and writing with streamer are done separately:
   353 		      - We only call the callback and write to the streamer when the streamer does not
   376 		      - We only call the callback and write to the streamer when the streamer does not
   359 		   stream's maximum length is, but I suspect 2*max(len_cvt, stream_len) is a good figure.
   382 		   stream's maximum length is, but I suspect 2*max(len_cvt, stream_len) is a good figure.
   360 		*/
   383 		*/
   361 		while (device->enabled) {
   384 		while (device->enabled) {
   362 			/* Only read in audio if the streamer doesn't have enough already (if it does not have enough samples to output) */
   385 			/* Only read in audio if the streamer doesn't have enough already (if it does not have enough samples to output) */
   363 			if(SDL_StreamLength(&device->streamer) < stream_len) {
   386 			if(SDL_StreamLength(&device->streamer) < stream_len) {
       
   387 				/* Set up istream */
       
   388 				if (device->convert.needed) {
       
   389 					if (device->convert.buf) {
       
   390 						istream = device->convert.buf;
       
   391 					} else {
       
   392 						continue;
       
   393 					}
       
   394 				} else {
       
   395 					istream = current_audio.impl.GetDeviceBuf(device);
       
   396 					if (istream == NULL) {
       
   397 						istream = device->fake_stream;
       
   398 					}
       
   399 				}
       
   400 			
   364 				/* Read from the callback into the _input_ stream */
   401 				/* Read from the callback into the _input_ stream */
   365 				if (!device->paused) {
   402 				if (!device->paused) {
   366 					SDL_mutexP(device->mixer_lock);
   403 					SDL_mutexP(device->mixer_lock);
   367 					(*fill) (udata, istream, istream_len);
   404 					(*fill) (udata, istream, istream_len);
   368 					SDL_mutexV(device->mixer_lock);
   405 					SDL_mutexV(device->mixer_lock);
   369 				}
   406 				}
   370 			
   407 			
   371 				 /* Convert the audio if necessary and write to the streamer */
   408 				 /* Convert the audio if necessary and write to the streamer */
   372 				if (device->convert.needed) {
   409 				if (device->convert.needed) {
   373 					SDL_ConvertAudio(&device->convert);
   410 					SDL_ConvertAudio(&device->convert);
   374 					istream = current_audio.impl.GetDeviceBuf(device);
       
   375 					if (istream == NULL) {
   411 					if (istream == NULL) {
   376 						istream = device->fake_stream;
   412 						istream = device->fake_stream;
   377 					}
   413 					}
   378 					SDL_memcpy(istream, device->convert.buf, device->convert.len_cvt);
   414 					/*SDL_memcpy(istream, device->convert.buf, device->convert.len_cvt);*/
   379 					SDL_StreamWrite(&device->streamer, istream, device->convert.len_cvt);
   415 					SDL_StreamWrite(&device->streamer, device->convert.buf, device->convert.len_cvt);
   380 				} else {
   416 				} else {
   381 					SDL_StreamWrite(&device->streamer, istream, istream_len);
   417 					SDL_StreamWrite(&device->streamer, istream, istream_len);
   382 				}
   418 				}
   383 			}
   419 			}
   384 		
   420 		
   465 		}
   501 		}
   466 	}
   502 	}
   467 
   503 
   468     /* Wait for the audio to drain.. */
   504     /* Wait for the audio to drain.. */
   469     current_audio.impl.WaitDone(device);
   505     current_audio.impl.WaitDone(device);
       
   506 	
       
   507 	/* If necessary, deinit the streamer */
       
   508 	if(device->use_streamer == 1) SDL_StreamDeinit(&device->streamer);
   470 
   509 
   471     return (0);
   510     return (0);
   472 }
   511 }
   473 
   512 
   474 
   513