0 bytes coming through GetAudioStreamData

I’m trying to get an AudioStream to feed data from the default playback device so I can then modify it e.g. apply a parametric EQ to the stream

The problem is I can’t get data from the AudioStream (verified with 0 bytes being read from the stream via GetAudioStreamData(output_stream, &buffer, max_bytes_to_fill)

Other things I’ve verified:

  • Audio spec creates
  • Correct output device
  • Audio stream opened successfully

Where am I making the mistake?

Any help would greatly be appreciated :slight_smile:

Here’s some of the code (note I’m using SDL3 with Odin):
```
// Setup the playback device
output_device : sdl.AudioDeviceID = sdl.OpenAudioDevice(sdl.AUDIO_DEVICE_DEFAULT_PLAYBACK, &desiredAudioSpec)

// Double check what the output device is
output_device_name : cstring = sdl.GetAudioDeviceName(output_device)

// Setup the stream
output_stream : ^sdl.AudioStream = sdl.OpenAudioDeviceStream(sdl.AUDIO_DEVICE_DEFAULT_PLAYBACK, &desiredAudioSpec, nil, nil)

// Error checking
if (output_stream == nil)
{
	fmt.printfln("No stream detected", sdl.GetError())
}

// Start the stream
// (Successfully opens)
audio_stream_opened : bool = sdl.ResumeAudioStreamDevice(output_stream)


running := true

for running {
	
	// Event handling - check for window close event
	event : sdl.Event
	for sdl.PollEvent(&event) 
	{
		#partial switch event.type 
		{
			case .QUIT:
				running = false
		}
	}



	minimum_audio : i32 = (8000 * size_of(f32)) / 2  /* 8000 float samples per second. Half of that. */
	buffer : [512]f32
	max_bytes_to_fill : i32 = size_of(buffer)
    
	// Checks if the number of bytes queued is less than the minimum audio, if so continue
    if (sdl.GetAudioStreamQueued(output_stream) < minimum_audio) 
    {
        
        // Get the audio data and store it into the buffer
        num_of_bytes_read_from_stream : i32 = sdl.GetAudioStreamData(output_stream, &buffer, max_bytes_to_fill)
        fmt.println("Num of bytes read from stream ",num_of_bytes_read_from_stream)

If I’m reading the code correctly, you open the default playback device and then request data back from it, but where are you filling it? Aren’t you just asking an empty device for the data that it contains, which is nothing?
Are you expecting it to be filled with data from a different running program?

On Linux you could set up an audio loop-back. Look into snd-aloop for that, then you could get output audio to feed as if it were running directly into a recorder. I don’t know of an analog to this on other platforms. … headphones might be a requirement to prevent nasty feedback.

My assumption was any audio that is sent to the AUDIO_DEVICE_DEFAULT_PLAYBACK would be sent / captured by the stream e.g. audio from a tab, where I could process it

SDL tends to be somewhat sandboxed from other running programs.

But look into the audio loop-back that I mentioned above, I think that’s the solution for you. Instructions for setting it up depend on what operating system you are on.

1 Like

Got a solution working:

  • Used VB-Audio Virtual Apps to create a playback and recording device

  • Setup the new recording device to take in the speaker audio

  • Used the SDL3 audio code to open device and relevant streams

  • Processed a buffer of data from the stream when it was available

  • Put the data back into the stream of the device I want to get the processed audio

We have an open bug to add a way to capture audio from other playing devices (so you play sound through, I don’t know, WinAmp or whatever, and you can open a capture device that will give you that audio as it is passing through to be played on the hardware), but this is not built into SDL yet.

As you figured out, for now, you can use external software to make fake devices that SDL thinks are real hardware, to accomplish this goal.

1 Like

(That open bug is Audio recording device · Issue #13317 · libsdl-org/SDL · GitHub )