Implemented streamer code in SDL_RunAudio() but have not tested it. gsoc2008_audio_resampling
authorAaron Wishnick
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 -
    1.19 -    /* Loop, filling the audio buffers */
    1.20 -    while (device->enabled) {
    1.21 -
    1.22 -        /* Fill the current buffer with sound */
    1.23 -        if (device->convert.needed) {
    1.24 -            if (device->convert.buf) {
    1.25 -                stream = device->convert.buf;
    1.26 -            } else {
    1.27 -                continue;
    1.28 -            }
    1.29 -        } else {
    1.30 -            stream = current_audio.impl.GetDeviceBuf(device);
    1.31 -            if (stream == NULL) {
    1.32 -                stream = device->fake_stream;
    1.33 -            }
    1.34 -        }
    1.35 +	if(device->use_streamer) {
    1.36 +		/* This code is almost the same as the old code. The difference is, instead of reding
    1.37 +		   directly from the callback into "stream", then converting and sending the audio off,
    1.38 +		   we go: callback -> "istream" -> (conversion) -> streamer -> stream -> device.
    1.39 +		   However, reading and writing with streamer are done separately:
    1.40 +		      - We only call the callback and write to the streamer when the streamer does not
    1.41 +			    contain enough samples to output to the device.
    1.42 +			  - We only read from the streamer and tell the device to play when the streamer
    1.43 +			    does have enough samples to output.
    1.44 +		   This allows us to perform resampling in the conversion step, where the output of the
    1.45 +		   resampling process can be any number. We will have to see what a good size for the
    1.46 +		   stream's maximum length is, but I suspect 2*max(len_cvt, stream_len) is a good figure.
    1.47 +		*/
    1.48 +		while (device->enabled) {
    1.49 +			/* Only read in audio if the streamer doesn't have enough already (if it does not have enough samples to output) */
    1.50 +			if(SDL_StreamLength(&device->streamer) < stream_len) {
    1.51 +				/* Read from the callback into the _input_ stream */
    1.52 +				if (!device->paused) {
    1.53 +					SDL_mutexP(device->mixer_lock);
    1.54 +					(*fill) (udata, istream, istream_len);
    1.55 +					SDL_mutexV(device->mixer_lock);
    1.56 +				}
    1.57 +			
    1.58 +				 /* Convert the audio if necessary and write to the streamer */
    1.59 +				if (device->convert.needed) {
    1.60 +					SDL_ConvertAudio(&device->convert);
    1.61 +					istream = current_audio.impl.GetDeviceBuf(device);
    1.62 +					if (istream == NULL) {
    1.63 +						istream = device->fake_stream;
    1.64 +					}
    1.65 +					SDL_memcpy(istream, device->convert.buf, device->convert.len_cvt);
    1.66 +					SDL_StreamWrite(&device->streamer, istream, device->convert.len_cvt);
    1.67 +				} else {
    1.68 +					SDL_StreamWrite(&device->streamer, istream, istream_len);
    1.69 +				}
    1.70 +			}
    1.71 +		
    1.72 +			/* Only output audio if the streamer has enough to output */
    1.73 +			if(SDL_StreamLength(&device->streamer) >= stream_len) {
    1.74 +				/* Set up the output stream */
    1.75 +				if (device->convert.needed) {
    1.76 +					if (device->convert.buf) {
    1.77 +						stream = device->convert.buf;
    1.78 +					} else {
    1.79 +						continue;
    1.80 +					}
    1.81 +				} else {
    1.82 +					stream = current_audio.impl.GetDeviceBuf(device);
    1.83 +					if (stream == NULL) {
    1.84 +						stream = device->fake_stream;
    1.85 +					}
    1.86 +				}
    1.87 +				
    1.88 +				/* Now read from the streamer */
    1.89 +				SDL_StreamRead(&device->streamer, stream, stream_len);
    1.90 +				
    1.91 +				 /* Ready current buffer for play and change current buffer */
    1.92 +				if (stream != device->fake_stream) {
    1.93 +					current_audio.impl.PlayDevice(device);
    1.94 +				}
    1.95  
    1.96 -        if (!device->paused) {
    1.97 -            SDL_mutexP(device->mixer_lock);
    1.98 -            (*fill) (udata, stream, stream_len);
    1.99 -            SDL_mutexV(device->mixer_lock);
   1.100 -        }
   1.101 +				/* Wait for an audio buffer to become available */
   1.102 +				if (stream == device->fake_stream) {
   1.103 +					SDL_Delay((device->spec.samples * 1000) / device->spec.freq);
   1.104 +				} else {
   1.105 +					current_audio.impl.WaitDevice(device);
   1.106 +				}
   1.107 +			}		
   1.108 +			
   1.109 +		}
   1.110 +	} else {
   1.111 +	/* Otherwise, do not use the streamer. This is the old code. */
   1.112 +    
   1.113 +		/* Loop, filling the audio buffers */
   1.114 +		while (device->enabled) {
   1.115 +
   1.116 +			/* Fill the current buffer with sound */
   1.117 +			if (device->convert.needed) {
   1.118 +				if (device->convert.buf) {
   1.119 +					stream = device->convert.buf;
   1.120 +				} else {
   1.121 +					continue;
   1.122 +				}
   1.123 +			} else {
   1.124 +				stream = current_audio.impl.GetDeviceBuf(device);
   1.125 +				if (stream == NULL) {
   1.126 +					stream = device->fake_stream;
   1.127 +				}
   1.128 +			}
   1.129  
   1.130 -        /* Convert the audio if necessary */
   1.131 -        if (device->convert.needed) {
   1.132 -            SDL_ConvertAudio(&device->convert);
   1.133 -            stream = current_audio.impl.GetDeviceBuf(device);
   1.134 -            if (stream == NULL) {
   1.135 -                stream = device->fake_stream;
   1.136 -            }
   1.137 -            SDL_memcpy(stream, device->convert.buf, device->convert.len_cvt);
   1.138 -        }
   1.139 +			if (!device->paused) {
   1.140 +				SDL_mutexP(device->mixer_lock);
   1.141 +				(*fill) (udata, stream, stream_len);
   1.142 +				SDL_mutexV(device->mixer_lock);
   1.143 +			}
   1.144  
   1.145 -        /* Ready current buffer for play and change current buffer */
   1.146 -        if (stream != device->fake_stream) {
   1.147 -            current_audio.impl.PlayDevice(device);
   1.148 -        }
   1.149 +			/* Convert the audio if necessary */
   1.150 +			if (device->convert.needed) {
   1.151 +				SDL_ConvertAudio(&device->convert);
   1.152 +				stream = current_audio.impl.GetDeviceBuf(device);
   1.153 +				if (stream == NULL) {
   1.154 +					stream = device->fake_stream;
   1.155 +				}
   1.156 +				SDL_memcpy(stream, device->convert.buf, device->convert.len_cvt);
   1.157 +			}
   1.158  
   1.159 -        /* Wait for an audio buffer to become available */
   1.160 -        if (stream == device->fake_stream) {
   1.161 -            SDL_Delay((device->spec.samples * 1000) / device->spec.freq);
   1.162 -        } else {
   1.163 -            current_audio.impl.WaitDevice(device);
   1.164 -        }
   1.165 -    }
   1.166 +			/* Ready current buffer for play and change current buffer */
   1.167 +			if (stream != device->fake_stream) {
   1.168 +				current_audio.impl.PlayDevice(device);
   1.169 +			}
   1.170 +
   1.171 +			/* Wait for an audio buffer to become available */
   1.172 +			if (stream == device->fake_stream) {
   1.173 +				SDL_Delay((device->spec.samples * 1000) / device->spec.freq);
   1.174 +			} else {
   1.175 +				current_audio.impl.WaitDevice(device);
   1.176 +			}
   1.177 +		}
   1.178 +	}
   1.179  
   1.180      /* Wait for the audio to drain.. */
   1.181      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  {