summaryrefslogtreecommitdiff
path: root/src/buffer
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2024-11-12 12:12:31 -0500
committerAndrew Opalach <andrew@akon.city> 2024-11-12 12:12:31 -0500
commit29fa4f8d667d543595e652e7402d395d507ba464 (patch)
treeeaa2adf9f687c499b31eeddef42493c4bfda9b1c /src/buffer
parentb4bcfa1da5c1be9f7999d4d4df4e8d1b73c3061a (diff)
downloadcamu-29fa4f8d667d543595e652e7402d395d507ba464.tar.gz
camu-29fa4f8d667d543595e652e7402d395d507ba464.tar.bz2
camu-29fa4f8d667d543595e652e7402d395d507ba464.zip
Add user volume, simple client add cli
Signed-off-by: Andrew Opalach <andrew@akon.city>
Diffstat (limited to 'src/buffer')
-rw-r--r--src/buffer/audio.c69
-rw-r--r--src/buffer/audio.h15
-rw-r--r--src/buffer/video.c6
-rw-r--r--src/buffer/volume.h30
4 files changed, 78 insertions, 42 deletions
diff --git a/src/buffer/audio.c b/src/buffer/audio.c
index 8d33f79..3abae42 100644
--- a/src/buffer/audio.c
+++ b/src/buffer/audio.c
@@ -9,12 +9,12 @@
#include "common_internal.h"
#include "volume.h"
-#define BUFFER_SIZE (6 * 1000000L)
-#define BUFFER_MARK_MIN (2.6 * 1000000L) // Must be a most half of the buffer size.
-#define BUFFER_MARK_BUFFERED (2.5 * 1000000L)
+#define BUFFER_SIZE (9 * 1000000L)
+#define BUFFER_MARK_MIN (4.3 * 1000000L) // Must be a most half of the buffer size.
+#define BUFFER_MARK_BUFFERED (4.0 * 1000000L)
#ifdef CAMU_AUDIO_BUFFER_FADE
-#define FADE_STEP(fmt) (1.1f / (fmt)->sample_rate)
+#define FADE_STEP(fmt) (1.f / (fmt)->sample_rate)
#endif
enum {
@@ -29,10 +29,11 @@ static void reset_buffer_state(struct camu_audio_buffer *buf)
{
buf->pts = -1.0;
buf->pause = PAUSE_PAUSED;
- al_atomic_store(u8)(&buf->unpause, 0, AL_ATOMIC_RELAXED);
- buf->volume = 1.f;
+ al_atomic_store(s32)(&buf->unpause, 0, AL_ATOMIC_RELAXED);
+ al_atomic_store(s32)(&buf->volume.set, 0, AL_ATOMIC_RELAXED);
#ifdef CAMU_AUDIO_BUFFER_FADE
- buf->fade_offset = 0;
+ buf->fade.offset = 0;
+ buf->fade.volume = 1.f;
#endif
buf->buffered = false;
al_atomic_store(u8)(&buf->flow, FLOWING, AL_ATOMIC_RELAXED);
@@ -88,6 +89,12 @@ bool camu_audio_buffer_configure(struct camu_audio_buffer *buf, struct camu_code
return true;
}
+void camu_audio_buffer_set_volume(struct camu_audio_buffer *buf, f32 volume)
+{
+ al_atomic_store(f32)(&buf->volume.queued, volume, AL_ATOMIC_RELAXED);
+ al_atomic_add(s32)(&buf->volume.set, 1, AL_ATOMIC_RELAXED);
+}
+
void camu_audio_buffer_set_latency(struct camu_audio_buffer *buf, f64 latency)
{
buf->latency = latency;
@@ -191,7 +198,7 @@ void camu_audio_buffer_push(struct camu_audio_buffer *buf, struct camu_codec_fra
void camu_audio_buffer_unpause(struct camu_audio_buffer *buf)
{
- al_atomic_store(u8)(&buf->unpause, 1, AL_ATOMIC_RELAXED);
+ al_atomic_add(s32)(&buf->unpause, 1, AL_ATOMIC_RELAXED);
}
// Not thread-safe, must be called while the buffer is not being read from or written to.
@@ -238,12 +245,23 @@ size_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, size_t re
return 0;
}
+ if (al_atomic_load(s32)(&buf->volume.set, AL_ATOMIC_ACQUIRE) > 0) {
+ buf->volume.user = al_atomic_load(f32)(&buf->volume.queued, AL_ATOMIC_RELAXED);
+#ifdef CAMU_AUDIO_BUFFER_FADE
+ if (buf->fade.volume == -1.f) {
+ buf->fade.volume = buf->volume.user;
+ }
+#endif
+ al_atomic_sub(s32)(&buf->volume.set, 1, AL_ATOMIC_RELEASE);
+ }
+
if (camu_clock_is_paused(buf->clock)) {
#ifdef CAMU_AUDIO_BUFFER_FADE
if (buf->pause == PAUSE_PLAYING) {
buf->pause = PAUSE_FADING;
- buf->fade_offset = 0;
- } else if (buf->volume == 0.f || buf->pause == PAUSE_PAUSED) {
+ buf->fade.offset = 0;
+ } else if (buf->fade.volume == 0.f || buf->pause == PAUSE_PAUSED) {
+ buf->fade.offset = 0;
al_memset(data, 0, req);
if (NOT_PAUSED(buf->pause)) {
buf->pause = PAUSE_PAUSED;
@@ -263,10 +281,10 @@ size_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, size_t re
#endif
}
- if (al_atomic_load(u8)(&buf->unpause, AL_ATOMIC_ACQUIRE)) {
+ if (al_atomic_load(s32)(&buf->unpause, AL_ATOMIC_ACQUIRE) > 0) {
// If pause != PLAYING here, this will cause unexpected behavior.
buf->pause = PAUSE_PAUSED;
- al_atomic_store(u8)(&buf->unpause, 0, AL_ATOMIC_RELEASE);
+ al_atomic_sub(s32)(&buf->unpause, 1, AL_ATOMIC_RELEASE);
}
f64 pts = camu_clock_get_pts(buf->clock, buf->latency);
@@ -274,8 +292,8 @@ size_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, size_t re
size_t have = al_ring_buffer_occupied(&buf->rb);
#ifdef CAMU_AUDIO_BUFFER_FADE
// Cut off fade if it's reaching too far.
- if (have < buf->fade_offset) have = 0;
- else have -= buf->fade_offset;
+ if (have < buf->fade.offset) have = 0;
+ else have -= buf->fade.offset;
if (buf->pause != PAUSE_FADING && buf->pause != PAUSE_PLAYING) {
#endif
pts -= buf->pts;
@@ -350,8 +368,8 @@ size_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, size_t re
if (buf->pause == PAUSE_FADING) {
// Peek into the ring buffer. This won't consume the data, so when
// we resume it will fade in from the same position the fade out started.
- ret = al_ring_buffer_peek(&buf->rb, data, buf->fade_offset, req);
- buf->fade_offset += ret;
+ ret = al_ring_buffer_peek(&buf->rb, data, buf->fade.offset, req);
+ buf->fade.offset += ret;
} else {
#endif
// Read as much as we determined we can.
@@ -361,19 +379,30 @@ size_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, size_t re
#ifdef CAMU_AUDIO_BUFFER_FADE
}
f32 step = 0.f;
- if (buf->pause == PAUSE_FADING) {
+ if (buf->pause == PAUSE_FADING || buf->fade.volume > buf->volume.user) {
step = -FADE_STEP(&buf->fmt.req);
- } else if (buf->volume < 1.f) {
+ } else if (buf->fade.volume < buf->volume.user) {
step = FADE_STEP(&buf->fmt.req);
}
- if (step != 0.f || buf->volume != 1.f) {
- buf->volume = apply_volume(data, req, &buf->fmt.req, buf->volume, step);
+ if (step != 0.f || buf->fade.volume != 1.f) {
+ if (buf->volume.user > 1.f) {
+ step *= buf->volume.user;
+ }
+ buf->fade.volume = apply_volume(data, req, &buf->fmt.req, buf->fade.volume, buf->volume.user, step);
+ }
+#else
+ if (buf->volume.user != 1.f) {
+ apply_volume(data, req, &buf->fmt.req, buf->volume.user, 0.f, 0.f);
}
#endif
}
// Check if we should request to uncork.
+#ifdef CAMU_AUDIO_BUFFER_FADE
+ if (flow == FLOWING && buf->pause != PAUSE_FADING) {
+#else
if (flow == FLOWING) {
+#endif
ret = al_atomic_load(size_t)(&buf->uncork_at, AL_ATOMIC_RELAXED);
if (ret && have - req <= ret) {
buf->callback(buf->userdata, CAMU_BUFFER_UNCORK);
diff --git a/src/buffer/audio.h b/src/buffer/audio.h
index 0f84d5a..1d49448 100644
--- a/src/buffer/audio.h
+++ b/src/buffer/audio.h
@@ -17,7 +17,7 @@ struct camu_audio_buffer {
f64 pts;
u8 pause;
- atomic(u8) unpause;
+ atomic(s32) unpause;
struct camu_clock *clock;
bool ignore_desync;
f64 latency;
@@ -36,9 +36,17 @@ struct camu_audio_buffer {
struct camu_peak_buffer peak;
atomic(size_t) uncork_at;
- f32 volume;
+ struct {
+ f32 user;
+ atomic(f32) queued;
+ atomic(s32) set;
+ } volume;
+
#ifdef CAMU_AUDIO_BUFFER_FADE
- size_t fade_offset;
+ struct {
+ f32 volume;
+ size_t offset;
+ } fade;
#endif
#ifdef CAMU_MIXER_THREADED
@@ -51,6 +59,7 @@ struct camu_audio_buffer {
bool camu_audio_buffer_init(struct camu_audio_buffer *buf, struct camu_clock *clock, struct camu_mixer *mixer);
bool camu_audio_buffer_configure(struct camu_audio_buffer *buf, struct camu_codec_stream *stream);
+void camu_audio_buffer_set_volume(struct camu_audio_buffer *buf, f32 volume);
void camu_audio_buffer_set_latency(struct camu_audio_buffer *buf, f64 latency);
void camu_audio_buffer_push(struct camu_audio_buffer *buf, struct camu_codec_frame *frame);
void camu_audio_buffer_unpause(struct camu_audio_buffer *buf);
diff --git a/src/buffer/video.c b/src/buffer/video.c
index 91c3687..a8b35c6 100644
--- a/src/buffer/video.c
+++ b/src/buffer/video.c
@@ -10,9 +10,9 @@
#endif
#endif
-#define BUFFER_MARK_LOW 0.199998
-#define BUFFER_MARK_BUFFERED 0.133332
-#define BUFFER_MARK_HIGH 0.33333
+#define BUFFER_MARK_LOW ((1.0 / 30.0) * 6)
+#define BUFFER_MARK_BUFFERED ((1.0 / 30.0) * 8)
+#define BUFFER_MARK_HIGH ((1.0 / 30.0) * 12)
#define BUFFER_MARK_RESET (BUFFER_MARK_HIGH * 2.0)
bool camu_video_buffer_init(struct camu_video_buffer *buf, struct camu_clock *clock, struct camu_renderer *renderer)
diff --git a/src/buffer/volume.h b/src/buffer/volume.h
index 0cad8d3..d39affc 100644
--- a/src/buffer/volume.h
+++ b/src/buffer/volume.h
@@ -2,26 +2,24 @@
AL_UNUSED_FUNCTION_PUSH
-// https://godbolt.org/#z:OYLghAFBqd5QCxAYwPYBMCmBRdBLAF1QCcAaPECAMzwBtMA7AQwFtMQByARg9KtQYEAysib0QXACx8BBAKoBnTAAUAHpwAMvAFYTStJg1AB9U8lJL6yAngGVG6AMKpaAVxYMQ0hwBk8DTAA5dwAjTGIvAFZSAAdUBUJbBmc3Dy9Y%2BMSBPwDgljCIyWjLTGskoQImYgIU909pErKBCqqCHKDQ8KiLSuratIbetv8O/K6igEoLVFdiZHYOAFIAJgBmf2Q3LABqRdXHBQJ8QQA6BD3sRY0AQRX1hk3XHb2Do6wqM4ur27WNrcxdvsqLRUEwCJ9Vpcbt87u8Rttrj5jABZa4ADQgTFI2xCE22%2BIJu0ijm%2BEEWAHYAEKEmm0ukExbE76E0wEACeMUwqCopkxeOMTEBABFtkw9tSiSSbizjOzOdzebjtsYQsKceL8YypdcWYKLsrVXsAGLKwUgA0awlamHkoUTGFrOEBBFI5EASUCmOxStp1puZKp9KD9L9OoJrI5XJ5xj5prVYtWEtDMrlUcV/MNqxFIUtyfDev2BsBJoF23NKstDKZ0Nt9uhjswNGdiOMjh812RyggDGxIOxCDweJb7s9A%2Bxw/RED72wYEzrtxuqfe238BAAHLLtgo1%2BLvkvG9tXKuNwRDzvE3vI8vV1wAGybhR33eLq8Ho%2BCO%2Bb1xPi8vznXwRVmWB8gOfa59yoQ9VyAr9QN/cDX0g1db0kB8ULAiCoMEFCv3Q%2BDL3/A9gVBU8qDgykCMwZd0BmEJ6G2Kg8Io6EbkOME8GQBigOVAUCAIYg8BCVwCEwUxtigBhUH8WgRjnUUYhiWg2WMAA3Fx3FEsjlmobiACp0DBLEtzwAAvUTTwUVhFNEtBXEEbEFG45AEEMAJaGMWz7K45ZtjU1JMGxLStxEmJ5wpZiw3xfhiHE1xuLwNUNA1BKXi3Kz6A8mZBGSlYKOWSk8XC5k6TwSCIBS5ZIm2ZzXMwdzPNPPYhSa7YNEKqliuDPyNLVFs2w7LturYXZ8uCzAYmxDQTiobEuGm%2B14JDW1OppRjJDSlhrLVagUImAzKkZSk8EZZrFrpSzNvo3SWqGzAwPpfaxUiI6Tu2rSJj69tOwgC7rOxI0fAAFRRD1/qBlF0QWiKVopZrpQJYhMAIWYGF89S2DA2GYRuVdthYJh/AgNS8HQMKOvhqLuMew6uGWSRlhO%2B6CSC261TmpKzvxVmWqYBSlNU9HNKAiBHtmunlmxCW0f8yaTg0LguCoKGVsR5HiFRjnodtDgploThIl4TxuF4VBOEcLcZjmAE7h4UgCE0HWpgAaxASJVhOLgAE5PbXenPciOnPdWLhoj1jhJENh3SFNjheAUEANDth2pjgWAkDQTa6HCchKAzmIs4iZBNkMYAuFWeW%2BDoETiHjiAQijkJ/CqNlOFtxvmGINkAHkQm0Up7eN0gM7YQQu4YJSo6wITgEcMRaHjwesHxoxxA4LRSHwRGyhUzAF/XzBVFKYSFlt1c6qjmSQmIZvnCwKP%2BLwFhW94HfiBCeJMCFTBl%2BAGSjGTvgBhgAKAAGp4EwAAdy7pyI2tt%2BCCBEGIdgUgZCCEUCodQa8dAgAlgYf%2BpgPL6EEvHSAUxUAxBsAIBeABaQ46AmrIG9tsahXcfLUPxnMc4WYTIMFfmwlgyMAhNR4Xwk2r8BJYBIRAKYjRKGeAgA4fonguCkF8CMPIBQ9BxASHIpRWjMhyPaBoroKjZHlCGHo0xdV%2B7mNaEYzoERTEWPRsonodj1EOIkDIy28wvH6H1pHLB0dODbFUGuW81CULVTwcAbYZc5Ye3ErgQgJARrBwmLwAeWg5ykBdpIW8Jw1waHlpEckGhJDkkiBoW8a5yT%2BPDoE9eMc44JyTlgnJYdliNJNpwTJycpivwSHYSQQA
-
-static inline f32 apply_volume_f32(f32 *data, size_t sample_count, s32 channel_count, f32 volume, f32 step)
+static inline f32 apply_volume_f32(f32 *data, size_t sample_count, s32 channel_count, f32 volume, f32 user, f32 step)
{
for (u32 i = 0; i < sample_count; i++) {
- if (i % channel_count == 0) {
- volume = AL_CLAMP(volume + step, 0.f, 1.f);
+ if (step != 0.f && i % channel_count == 0) {
+ volume = AL_CLAMP(volume + step, 0.f, user);
}
f64 sample = (f64)data[i];
sample *= volume;
- data[i] = (f32)AL_CLAMP(sample, FLT_MIN, FLT_MAX);
+ data[i] = (f32)AL_CLAMP(sample, -1.0, 1.0);
}
return volume;
}
-static inline f32 apply_volume_s32(s32 *data, size_t sample_count, s32 channel_count, f32 volume, f32 step)
+static inline f32 apply_volume_s32(s32 *data, size_t sample_count, s32 channel_count, f32 volume, f32 user, f32 step)
{
for (u32 i = 0; i < sample_count; i++) {
- if (i % channel_count == 0) {
- volume = AL_CLAMP(volume + step, 0.f, 1.f);
+ if (step != 0.f && i % channel_count == 0) {
+ volume = AL_CLAMP(volume + step, 0.f, user);
}
f64 sample = (f64)data[i];
sample *= volume;
@@ -30,11 +28,11 @@ static inline f32 apply_volume_s32(s32 *data, size_t sample_count, s32 channel_c
return volume;
}
-static inline f32 apply_volume_s16(s16 *data, size_t sample_count, s32 channel_count, f32 volume, f32 step)
+static inline f32 apply_volume_s16(s16 *data, size_t sample_count, s32 channel_count, f32 volume, f32 user, f32 step)
{
for (u32 i = 0; i < sample_count; i++) {
- if (i % channel_count == 0) {
- volume = AL_CLAMP(volume + step, 0.f, 1.f);
+ if (step != 0.f && i % channel_count == 0) {
+ volume = AL_CLAMP(volume + step, 0.f, user);
}
f64 sample = (f64)data[i];
sample *= volume;
@@ -43,22 +41,22 @@ static inline f32 apply_volume_s16(s16 *data, size_t sample_count, s32 channel_c
return volume;
}
-static inline f32 apply_volume(u8 *data, size_t size, struct camu_audio_format *fmt, f32 volume, f32 step)
+static inline f32 apply_volume(u8 *data, size_t size, struct camu_audio_format *fmt, f32 volume, f32 user, f32 step)
{
size_t sample_count;
switch (camu_audio_format_bytes_per_sample(fmt)) {
case 4:
sample_count = size / 4;
if (fmt->format == CAMU_SAMPLE_FORMAT_S32) {
- return apply_volume_s32((s32 *)data, sample_count, fmt->channel_count, volume, step);
+ return apply_volume_s32((s32 *)data, sample_count, fmt->channel_count, volume, user, step);
} else if (fmt->format == CAMU_SAMPLE_FORMAT_FLT) {
- return apply_volume_f32((f32 *)data, sample_count, fmt->channel_count, volume, step);
+ return apply_volume_f32((f32 *)data, sample_count, fmt->channel_count, volume, user, step);
}
break;
case 2:
sample_count = size / 2;
if (fmt->format == CAMU_SAMPLE_FORMAT_S16) {
- return apply_volume_s16((s16 *)data, sample_count, fmt->channel_count, volume, step);
+ return apply_volume_s16((s16 *)data, sample_count, fmt->channel_count, volume, user, step);
}
break;
}