mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-10 08:38:20 +00:00
[client] audio: drain buffers on stop instead of just discarding them
This commit is contained in:
parent
b334f22223
commit
07c92ec2e8
@ -28,14 +28,25 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
STREAM_STATE_STOP,
|
||||||
|
STREAM_STATE_SETUP,
|
||||||
|
STREAM_STATE_RUN,
|
||||||
|
STREAM_STATE_DRAIN
|
||||||
|
}
|
||||||
|
StreamState;
|
||||||
|
|
||||||
|
#define STREAM_ACTIVE(state) \
|
||||||
|
(state == STREAM_STATE_SETUP || state == STREAM_STATE_RUN)
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
struct LG_AudioDevOps * audioDev;
|
struct LG_AudioDevOps * audioDev;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
bool setup;
|
StreamState state;
|
||||||
bool started;
|
|
||||||
int volumeChannels;
|
int volumeChannels;
|
||||||
uint16_t volume[8];
|
uint16_t volume[8];
|
||||||
bool mute;
|
bool mute;
|
||||||
@ -107,15 +118,34 @@ static const char * audioGraphFormatFn(const char * name,
|
|||||||
return title;
|
return title;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void playbackStopNL(void)
|
||||||
|
{
|
||||||
|
audio.playback.state = STREAM_STATE_STOP;
|
||||||
|
audio.audioDev->playback.stop();
|
||||||
|
ringbuffer_free(&audio.playback.buffer);
|
||||||
|
|
||||||
|
if (audio.playback.timings)
|
||||||
|
{
|
||||||
|
app_unregisterGraph(audio.playback.graph);
|
||||||
|
ringbuffer_free(&audio.playback.timings);
|
||||||
|
}
|
||||||
|
|
||||||
|
audio.playback.state = STREAM_STATE_STOP;
|
||||||
|
}
|
||||||
|
|
||||||
static int playbackPullFrames(uint8_t ** data, int frames)
|
static int playbackPullFrames(uint8_t ** data, int frames)
|
||||||
{
|
{
|
||||||
LG_LOCK(audio.playback.lock);
|
LG_LOCK(audio.playback.lock);
|
||||||
|
|
||||||
if (audio.playback.buffer)
|
if (audio.playback.buffer)
|
||||||
*data = ringbuffer_consume(audio.playback.buffer, &frames);
|
*data = ringbuffer_consume(audio.playback.buffer, &frames);
|
||||||
else
|
else
|
||||||
frames = 0;
|
frames = 0;
|
||||||
LG_UNLOCK(audio.playback.lock);
|
|
||||||
|
|
||||||
|
if (audio.playback.state == STREAM_STATE_DRAIN && frames == 0)
|
||||||
|
playbackStopNL();
|
||||||
|
|
||||||
|
LG_UNLOCK(audio.playback.lock);
|
||||||
return frames;
|
return frames;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,18 +155,18 @@ void audio_playbackStart(int channels, int sampleRate, PSAudioFormat format,
|
|||||||
if (!audio.audioDev)
|
if (!audio.audioDev)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
LG_LOCK(audio.playback.lock);
|
||||||
|
|
||||||
static int lastChannels = 0;
|
static int lastChannels = 0;
|
||||||
static int lastSampleRate = 0;
|
static int lastSampleRate = 0;
|
||||||
|
|
||||||
if (audio.playback.setup)
|
if (STREAM_ACTIVE(audio.playback.state))
|
||||||
{
|
{
|
||||||
if (channels != lastChannels || sampleRate != lastSampleRate)
|
if (channels == lastChannels && sampleRate == lastSampleRate)
|
||||||
audio.audioDev->playback.stop();
|
goto no_change;
|
||||||
else
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
LG_LOCK(audio.playback.lock);
|
playbackStopNL();
|
||||||
|
}
|
||||||
|
|
||||||
const int bufferFrames = sampleRate / 10;
|
const int bufferFrames = sampleRate / 10;
|
||||||
audio.playback.buffer = ringbuffer_new(bufferFrames,
|
audio.playback.buffer = ringbuffer_new(bufferFrames,
|
||||||
@ -147,7 +177,7 @@ void audio_playbackStart(int channels, int sampleRate, PSAudioFormat format,
|
|||||||
|
|
||||||
audio.playback.sampleRate = sampleRate;
|
audio.playback.sampleRate = sampleRate;
|
||||||
audio.playback.stride = channels * sizeof(uint16_t);
|
audio.playback.stride = channels * sizeof(uint16_t);
|
||||||
audio.playback.setup = true;
|
audio.playback.state = STREAM_STATE_SETUP;
|
||||||
|
|
||||||
audio.audioDev->playback.setup(channels, sampleRate, playbackPullFrames);
|
audio.audioDev->playback.setup(channels, sampleRate, playbackPullFrames);
|
||||||
|
|
||||||
@ -166,28 +196,19 @@ void audio_playbackStart(int channels, int sampleRate, PSAudioFormat format,
|
|||||||
audio.playback.graph = app_registerGraph("PLAYBACK",
|
audio.playback.graph = app_registerGraph("PLAYBACK",
|
||||||
audio.playback.timings, 0.0f, 100.0f, audioGraphFormatFn);
|
audio.playback.timings, 0.0f, 100.0f, audioGraphFormatFn);
|
||||||
|
|
||||||
|
audio.playback.state = STREAM_STATE_SETUP;
|
||||||
|
|
||||||
|
no_change:
|
||||||
LG_UNLOCK(audio.playback.lock);
|
LG_UNLOCK(audio.playback.lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_playbackStop(void)
|
void audio_playbackStop(void)
|
||||||
{
|
{
|
||||||
if (!audio.audioDev || !audio.playback.started)
|
if (!audio.audioDev || audio.playback.state == STREAM_STATE_STOP)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
LG_LOCK(audio.playback.lock);
|
audio.playback.state = STREAM_STATE_DRAIN;
|
||||||
|
return;
|
||||||
audio.audioDev->playback.stop();
|
|
||||||
audio.playback.setup = false;
|
|
||||||
audio.playback.started = false;
|
|
||||||
ringbuffer_free(&audio.playback.buffer);
|
|
||||||
|
|
||||||
if (audio.playback.timings)
|
|
||||||
{
|
|
||||||
app_unregisterGraph(audio.playback.graph);
|
|
||||||
ringbuffer_free(&audio.playback.timings);
|
|
||||||
}
|
|
||||||
|
|
||||||
LG_UNLOCK(audio.playback.lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_playbackVolume(int channels, const uint16_t volume[])
|
void audio_playbackVolume(int channels, const uint16_t volume[])
|
||||||
@ -200,7 +221,7 @@ void audio_playbackVolume(int channels, const uint16_t volume[])
|
|||||||
memcpy(audio.playback.volume, volume, sizeof(uint16_t) * channels);
|
memcpy(audio.playback.volume, volume, sizeof(uint16_t) * channels);
|
||||||
audio.playback.volumeChannels = channels;
|
audio.playback.volumeChannels = channels;
|
||||||
|
|
||||||
if (!audio.playback.setup)
|
if (!STREAM_ACTIVE(audio.playback.state))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
audio.audioDev->playback.volume(channels, volume);
|
audio.audioDev->playback.volume(channels, volume);
|
||||||
@ -213,7 +234,7 @@ void audio_playbackMute(bool mute)
|
|||||||
|
|
||||||
// store the value so we can restore it if the stream is restarted
|
// store the value so we can restore it if the stream is restarted
|
||||||
audio.playback.mute = mute;
|
audio.playback.mute = mute;
|
||||||
if (!audio.playback.setup)
|
if (!STREAM_ACTIVE(audio.playback.state))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
audio.audioDev->playback.mute(mute);
|
audio.audioDev->playback.mute(mute);
|
||||||
@ -221,7 +242,10 @@ void audio_playbackMute(bool mute)
|
|||||||
|
|
||||||
void audio_playbackData(uint8_t * data, size_t size)
|
void audio_playbackData(uint8_t * data, size_t size)
|
||||||
{
|
{
|
||||||
if (!audio.audioDev || !audio.playback.setup)
|
if (!audio.audioDev)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!STREAM_ACTIVE(audio.playback.state))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const int frames = size / audio.playback.stride;
|
const int frames = size / audio.playback.stride;
|
||||||
@ -229,10 +253,11 @@ void audio_playbackData(uint8_t * data, size_t size)
|
|||||||
|
|
||||||
// don't start playback until the buffer is sifficiently full to avoid
|
// don't start playback until the buffer is sifficiently full to avoid
|
||||||
// glitches
|
// glitches
|
||||||
if (!audio.playback.started && ringbuffer_getCount(audio.playback.buffer) >=
|
if (audio.playback.state == STREAM_STATE_SETUP &&
|
||||||
|
ringbuffer_getCount(audio.playback.buffer) >=
|
||||||
ringbuffer_getLength(audio.playback.buffer) / 4)
|
ringbuffer_getLength(audio.playback.buffer) / 4)
|
||||||
{
|
{
|
||||||
audio.playback.started = true;
|
audio.playback.state = STREAM_STATE_RUN;
|
||||||
audio.audioDev->playback.start();
|
audio.audioDev->playback.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user