Implemented streamer code in SDL_RunAudio() but have not tested it. gsoc2008_audio_resampling
authorAaron Wishnick <schnarf@gmail.com>
Wed, 13 Aug 2008 02:50:10 +0000
branchgsoc2008_audio_resampling
changeset 2666e12ccc6c9576
parent 2665 f39a056aec8b
child 2667 4174e511655f
Implemented streamer code in SDL_RunAudio() but have not tested it.
src/audio/SDL_audio.c
src/audio/SDL_sysaudio.h
     1.1 --- a/src/audio/SDL_audio.c	Tue Aug 12 01:03:05 2008 +0000
     1.2 +++ b/src/audio/SDL_audio.c	Wed Aug 13 02:50:10 2008 +0000
     1.3 @@ -319,6 +319,10 @@
     1.4      void *udata;
     1.5      void (SDLCALL * fill) (void *userdata, Uint8 * stream, int len);
     1.6      int silence;
     1.7 +	
     1.8 +	/* For streaming when the buffer sizes don't match up */
     1.9 +	Uint8 *istream;
    1.10 +	int istream_len;
    1.11  
    1.12      /* Perform any thread setup */
    1.13      device->threadid = SDL_ThreadID();
    1.14 @@ -341,52 +345,125 @@
    1.15      }
    1.16  	
    1.17  	/* Determine if the streamer is necessary here */
    1.18 +	if(device->use_streamer) {
    1.19 +		/* This code is almost the same as the old code. The difference is, instead of reding
    1.20 +		   directly from the callback into "stream", then converting and sending the audio off,
    1.21 +		   we go: callback -> "istream" -> (conversion) -> streamer -> stream -> device.
    1.22 +		   However, reading and writing with streamer are done separately:
    1.23 +		      - We only call the callback and write to the streamer when the streamer does not
    1.24 +			    contain enough samples to output to the device.
    1.25 +			  - We only read from the streamer and tell the device to play when the streamer
    1.26 +			    does have enough samples to output.
    1.27 +		   This allows us to perform resampling in the conversion step, where the output of the
    1.28 +		   resampling process can be any number. We will have to see what a good size for the
    1.29 +		   stream's maximum length is, but I suspect 2*max(len_cvt, stream_len) is a good figure.
    1.30 +		*/
    1.31 +		while (device->enabled) {
    1.32 +			/* Only read in audio if the streamer doesn't have enough already (if it does not have enough samples to output) */
    1.33 +			if(SDL_StreamLength(&device->streamer) < stream_len) {
    1.34 +				/* Read from the callback into the _input_ stream */
    1.35 +				if (!device->paused) {
    1.36 +					SDL_mutexP(device->mixer_lock);
    1.37 +					(*fill) (udata, istream, istream_len);
    1.38 +					SDL_mutexV(device->mixer_lock);
    1.39 +				}
    1.40 +			
    1.41 +				 /* Convert the audio if necessary and write to the streamer */
    1.42 +				if (device->convert.needed) {
    1.43 +					SDL_ConvertAudio(&device->convert);
    1.44 +					istream = current_audio.impl.GetDeviceBuf(device);
    1.45 +					if (istream == NULL) {
    1.46 +						istream = device->fake_stream;
    1.47 +					}
    1.48 +					SDL_memcpy(istream, device->convert.buf, device->convert.len_cvt);
    1.49 +					SDL_StreamWrite(&device->streamer, istream, device->convert.len_cvt);
    1.50 +				} else {
    1.51 +					SDL_StreamWrite(&device->streamer, istream, istream_len);
    1.52 +				}
    1.53 +			}
    1.54 +		
    1.55 +			/* Only output audio if the streamer has enough to output */
    1.56 +			if(SDL_StreamLength(&device->streamer) >= stream_len) {
    1.57 +				/* Set up the output stream */
    1.58 +				if (device->convert.needed) {
    1.59 +					if (device->convert.buf) {
    1.60 +						stream = device->convert.buf;
    1.61 +					} else {
    1.62 +						continue;
    1.63 +					}
    1.64 +				} else {
    1.65 +					stream = current_audio.impl.GetDeviceBuf(device);
    1.66 +					if (stream == NULL) {
    1.67 +						stream = device->fake_stream;
    1.68 +					}
    1.69 +				}
    1.70 +				
    1.71 +				/* Now read from the streamer */
    1.72 +				SDL_StreamRead(&device->streamer, stream, stream_len);
    1.73 +				
    1.74 +				 /* Ready current buffer for play and change current buffer */
    1.75 +				if (stream != device->fake_stream) {
    1.76 +					current_audio.impl.PlayDevice(device);
    1.77 +				}
    1.78  
    1.79 -    /* Loop, filling the audio buffers */
    1.80 -    while (device->enabled) {
    1.81 +				/* Wait for an audio buffer to become available */
    1.82 +				if (stream == device->fake_stream) {
    1.83 +					SDL_Delay((device->spec.samples * 1000) / device->spec.freq);
    1.84 +				} else {
    1.85 +					current_audio.impl.WaitDevice(device);
    1.86 +				}
    1.87 +			}		
    1.88 +			
    1.89 +		}
    1.90 +	} else {
    1.91 +	/* Otherwise, do not use the streamer. This is the old code. */
    1.92 +    
    1.93 +		/* Loop, filling the audio buffers */
    1.94 +		while (device->enabled) {
    1.95  
    1.96 -        /* Fill the current buffer with sound */
    1.97 -        if (device->convert.needed) {
    1.98 -            if (device->convert.buf) {
    1.99 -                stream = device->convert.buf;
   1.100 -            } else {
   1.101 -                continue;
   1.102 -            }
   1.103 -        } else {
   1.104 -            stream = current_audio.impl.GetDeviceBuf(device);
   1.105 -            if (stream == NULL) {
   1.106 -                stream = device->fake_stream;
   1.107 -            }
   1.108 -        }
   1.109 +			/* Fill the current buffer with sound */
   1.110 +			if (device->convert.needed) {
   1.111 +				if (device->convert.buf) {
   1.112 +					stream = device->convert.buf;
   1.113 +				} else {
   1.114 +					continue;
   1.115 +				}
   1.116 +			} else {
   1.117 +				stream = current_audio.impl.GetDeviceBuf(device);
   1.118 +				if (stream == NULL) {
   1.119 +					stream = device->fake_stream;
   1.120 +				}
   1.121 +			}
   1.122  
   1.123 -        if (!device->paused) {
   1.124 -            SDL_mutexP(device->mixer_lock);
   1.125 -            (*fill) (udata, stream, stream_len);
   1.126 -            SDL_mutexV(device->mixer_lock);
   1.127 -        }
   1.128 +			if (!device->paused) {
   1.129 +				SDL_mutexP(device->mixer_lock);
   1.130 +				(*fill) (udata, stream, stream_len);
   1.131 +				SDL_mutexV(device->mixer_lock);
   1.132 +			}
   1.133  
   1.134 -        /* Convert the audio if necessary */
   1.135 -        if (device->convert.needed) {
   1.136 -            SDL_ConvertAudio(&device->convert);
   1.137 -            stream = current_audio.impl.GetDeviceBuf(device);
   1.138 -            if (stream == NULL) {
   1.139 -                stream = device->fake_stream;
   1.140 -            }
   1.141 -            SDL_memcpy(stream, device->convert.buf, device->convert.len_cvt);
   1.142 -        }
   1.143 +			/* Convert the audio if necessary */
   1.144 +			if (device->convert.needed) {
   1.145 +				SDL_ConvertAudio(&device->convert);
   1.146 +				stream = current_audio.impl.GetDeviceBuf(device);
   1.147 +				if (stream == NULL) {
   1.148 +					stream = device->fake_stream;
   1.149 +				}
   1.150 +				SDL_memcpy(stream, device->convert.buf, device->convert.len_cvt);
   1.151 +			}
   1.152  
   1.153 -        /* Ready current buffer for play and change current buffer */
   1.154 -        if (stream != device->fake_stream) {
   1.155 -            current_audio.impl.PlayDevice(device);
   1.156 -        }
   1.157 +			/* Ready current buffer for play and change current buffer */
   1.158 +			if (stream != device->fake_stream) {
   1.159 +				current_audio.impl.PlayDevice(device);
   1.160 +			}
   1.161  
   1.162 -        /* Wait for an audio buffer to become available */
   1.163 -        if (stream == device->fake_stream) {
   1.164 -            SDL_Delay((device->spec.samples * 1000) / device->spec.freq);
   1.165 -        } else {
   1.166 -            current_audio.impl.WaitDevice(device);
   1.167 -        }
   1.168 -    }
   1.169 +			/* Wait for an audio buffer to become available */
   1.170 +			if (stream == device->fake_stream) {
   1.171 +				SDL_Delay((device->spec.samples * 1000) / device->spec.freq);
   1.172 +			} else {
   1.173 +				current_audio.impl.WaitDevice(device);
   1.174 +			}
   1.175 +		}
   1.176 +	}
   1.177  
   1.178      /* Wait for the audio to drain.. */
   1.179      current_audio.impl.WaitDone(device);
     2.1 --- a/src/audio/SDL_sysaudio.h	Tue Aug 12 01:03:05 2008 +0000
     2.2 +++ b/src/audio/SDL_sysaudio.h	Wed Aug 13 02:50:10 2008 +0000
     2.3 @@ -68,6 +68,7 @@
     2.4      SDL_AudioDriverImpl impl;
     2.5  } SDL_AudioDriver;
     2.6  
     2.7 +
     2.8  /* Streamer */
     2.9  typedef struct
    2.10  {