Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SDL: Add Audio Device Change Event #34

Merged
merged 3 commits into from
Jun 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 29 additions & 19 deletions TuneLab/Audio/SDL2/SDLAudioEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,20 @@ internal class SDLAudioEngine : IAudioEngine
public event Action? PlayStateChanged;
public event Action? ProgressChanged;

public event Action? DeviceChanged;

public event Action? DevicesUpdated;

public bool IsPlaying => _d.state == SDLPlaybackData.PlaybackState.Playing;

public int SamplingRate => 44100;

public double CurrentTime => (double)_lastPosition / SamplingRate;

public int CurrentDeviceIndex => _deviceIndex;

public string CurrentDriver => _d.driver;

public void Init(IAudioProcessor processor)
{
var context = SynchronizationContext.Current;
Expand All @@ -38,22 +46,22 @@ public void Init(IAudioProcessor processor)
_d = new SDLPlaybackData();

// 转发事件:设备更改
_d.devChanged = (newVal, oldVal) =>
_d.devChanged = (newVal, oldVal) => { context.Post(_ => { DeviceChanged?.Invoke(); }, null); };
// 转发事件:播放状态更改
_d.stateChanged = (newVal, oldVal) =>
{
context.Post(_ =>
{
// ...
PlayStateChanged?.Invoke(); //
}, null);
// Console.WriteLine($"SDLPLayback: Audio device change to {newVal}.");
};
// 转发事件:播放状态更改
_d.stateChanged = (newVal, oldVal) =>
// 转发事件:设备列表更新
_d.devicesUpdated = () =>
{
context.Post(_ =>
{
PlayStateChanged?.Invoke(); //
DevicesUpdated?.Invoke(); //
}, null);
// Console.WriteLine($"SDLPLayback: Play state change to {newVal}.");
};
// 转发事件:当前缓冲区被播放
_d.samplesConsumed = val =>
Expand Down Expand Up @@ -107,7 +115,7 @@ public void Play()
return;
}

// 如果没有打开音频设备那么打开第一个音频设备
// 如果没有打开音频设备那么打开默认音频设备
if (_d.curDevId == 0)
{
SwitchDevice(-1);
Expand Down Expand Up @@ -150,32 +158,33 @@ public void SwitchDevice(int deviceNumber)
{
if (_d.state == SDLPlaybackData.PlaybackState.Playing)
{
Console.WriteLine("SDLPlayback: Don't change audio device when playing.");
Console.WriteLine("SDL: Don't change audio device when playing.");
return;
}

// 打开音频设备
uint id;
string? deviceToOpen = deviceNumber < 0 ? null : SDL.SDL_GetAudioDeviceName(deviceNumber, 0);
if (deviceToOpen == null)
{
Console.WriteLine($"SDL: Open default device");
}
else
{
Console.WriteLine($"SDL: Open \"{deviceToOpen}\"");
}

if ((id = SDL.SDL_OpenAudioDevice(
deviceToOpen,
0,
ref _d.spec,
out _,
0)) == 0)
{
throw new IOException($"SDLPlayback: Failed to open audio device: {SDL.SDL_GetError()}.");
}

if (deviceToOpen == null)
{
Console.WriteLine($"SDLPlayback: Current Device");
}
else
{
Console.WriteLine($"SDLPlayback: {deviceToOpen}");
throw new IOException($"SDL: Failed to open audio device: {SDL.SDL_GetError()}.");
}

_deviceIndex = deviceNumber;
_d.setDevId(id);
}

Expand Down Expand Up @@ -211,6 +220,7 @@ public void SwitchDriver(string driver)

// SDL 相关
private SDLPlaybackData _d;
private int _deviceIndex = 0;

private class SampleProvider(SDLAudioEngine engine) : ISampleProvider
{
Expand Down
2 changes: 2 additions & 0 deletions TuneLab/Audio/SDL2/SDLGlobal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ public enum UserEvent

public delegate void ValueEvent<T>(T val);

public delegate void VoidEvent();

public static void FloatsToBytes(float[] floats, byte[] bytes, int size)
{
for (int i = 0; i < size; i++)
Expand Down
18 changes: 14 additions & 4 deletions TuneLab/Audio/SDL2/SDLPlaybackData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ public enum PlaybackState

public SDLGlobal.ValueEvent<int>? samplesConsumed;

public SDLGlobal.VoidEvent? devicesUpdated;

// 播放信息
public string driver = "";
public string driver = string.Empty;

public PlaybackState state = PlaybackState.Stopped;

Expand Down Expand Up @@ -103,7 +105,6 @@ public void setDevId(uint newId)
{
var orgId = curDevId;
curDevId = newId;

if (orgId > 0)
{
SDL.SDL_CloseAudioDevice(orgId);
Expand Down Expand Up @@ -254,6 +255,14 @@ public void poll()
break;
}

case (int)SDL.SDL_EventType.SDL_AUDIODEVICEADDED:
{
// 重新检测音频设备
_ = SDL.SDL_GetNumAudioDevices(0);
devicesUpdated?.Invoke();
break;
}

// 音频设备移除
case (int)SDL.SDL_EventType.SDL_AUDIODEVICEREMOVED:
{
Expand All @@ -264,10 +273,11 @@ public void poll()
over = true;
}

// 重新检测音频设备
_ = SDL.SDL_GetNumAudioDevices(0);
devicesUpdated?.Invoke();
break;
}
default:
break;
}
}

Expand Down
Loading