[PATCH 1/3] winepulse.drv: Move pulse_write helper around.
Rémi Bernon
rbernon at codeweavers.com
Tue Oct 26 10:37:14 CDT 2021
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
dlls/winepulse.drv/pulse.c | 380 ++++++++++++++++++-------------------
1 file changed, 190 insertions(+), 190 deletions(-)
diff --git a/dlls/winepulse.drv/pulse.c b/dlls/winepulse.drv/pulse.c
index 98b4a1ec964..590122cc7b1 100644
--- a/dlls/winepulse.drv/pulse.c
+++ b/dlls/winepulse.drv/pulse.c
@@ -270,6 +270,196 @@ static void pulse_started_callback(pa_stream *s, void *userdata)
TRACE("%p: (Re)started playing\n", userdata);
}
+static void silence_buffer(pa_sample_format_t format, BYTE *buffer, UINT32 bytes)
+{
+ memset(buffer, format == PA_SAMPLE_U8 ? 0x80 : 0, bytes);
+}
+
+static int write_buffer(const struct pulse_stream *stream, BYTE *buffer, UINT32 bytes)
+{
+ const float *vol = stream->vol;
+ UINT32 i, channels, mute = 0;
+ BOOL adjust = FALSE;
+ BYTE *end;
+
+ if (!bytes) return 0;
+
+ /* Adjust the buffer based on the volume for each channel */
+ channels = stream->ss.channels;
+ for (i = 0; i < channels; i++)
+ {
+ adjust |= vol[i] != 1.0f;
+ if (vol[i] == 0.0f)
+ mute++;
+ }
+ if (mute == channels)
+ {
+ silence_buffer(stream->ss.format, buffer, bytes);
+ goto write;
+ }
+ if (!adjust) goto write;
+
+ end = buffer + bytes;
+ switch (stream->ss.format)
+ {
+#ifndef WORDS_BIGENDIAN
+#define PROCESS_BUFFER(type) do \
+{ \
+ type *p = (type*)buffer; \
+ do \
+ { \
+ for (i = 0; i < channels; i++) \
+ p[i] = p[i] * vol[i]; \
+ p += i; \
+ } while ((BYTE*)p != end); \
+} while (0)
+ case PA_SAMPLE_S16LE:
+ PROCESS_BUFFER(INT16);
+ break;
+ case PA_SAMPLE_S32LE:
+ PROCESS_BUFFER(INT32);
+ break;
+ case PA_SAMPLE_FLOAT32LE:
+ PROCESS_BUFFER(float);
+ break;
+#undef PROCESS_BUFFER
+ case PA_SAMPLE_S24_32LE:
+ {
+ UINT32 *p = (UINT32*)buffer;
+ do
+ {
+ for (i = 0; i < channels; i++)
+ {
+ p[i] = (INT32)((INT32)(p[i] << 8) * vol[i]);
+ p[i] >>= 8;
+ }
+ p += i;
+ } while ((BYTE*)p != end);
+ break;
+ }
+ case PA_SAMPLE_S24LE:
+ {
+ /* do it 12 bytes at a time until it is no longer possible */
+ UINT32 *q = (UINT32*)buffer;
+ BYTE *p;
+
+ i = 0;
+ while (end - (BYTE*)q >= 12)
+ {
+ UINT32 v[4], k;
+ v[0] = q[0] << 8;
+ v[1] = q[1] << 16 | (q[0] >> 16 & ~0xff);
+ v[2] = q[2] << 24 | (q[1] >> 8 & ~0xff);
+ v[3] = q[2] & ~0xff;
+ for (k = 0; k < 4; k++)
+ {
+ v[k] = (INT32)((INT32)v[k] * vol[i]);
+ if (++i == channels) i = 0;
+ }
+ *q++ = v[0] >> 8 | (v[1] & ~0xff) << 16;
+ *q++ = v[1] >> 16 | (v[2] & ~0xff) << 8;
+ *q++ = v[2] >> 24 | (v[3] & ~0xff);
+ }
+ p = (BYTE*)q;
+ while (p != end)
+ {
+ UINT32 v = (INT32)((INT32)(p[0] << 8 | p[1] << 16 | p[2] << 24) * vol[i]);
+ *p++ = v >> 8 & 0xff;
+ *p++ = v >> 16 & 0xff;
+ *p++ = v >> 24;
+ if (++i == channels) i = 0;
+ }
+ break;
+ }
+#endif
+ case PA_SAMPLE_U8:
+ {
+ UINT8 *p = (UINT8*)buffer;
+ do
+ {
+ for (i = 0; i < channels; i++)
+ p[i] = (int)((p[i] - 128) * vol[i]) + 128;
+ p += i;
+ } while ((BYTE*)p != end);
+ break;
+ }
+ case PA_SAMPLE_ALAW:
+ {
+ UINT8 *p = (UINT8*)buffer;
+ do
+ {
+ for (i = 0; i < channels; i++)
+ p[i] = mult_alaw_sample(p[i], vol[i]);
+ p += i;
+ } while ((BYTE*)p != end);
+ break;
+ }
+ case PA_SAMPLE_ULAW:
+ {
+ UINT8 *p = (UINT8*)buffer;
+ do
+ {
+ for (i = 0; i < channels; i++)
+ p[i] = mult_ulaw_sample(p[i], vol[i]);
+ p += i;
+ } while ((BYTE*)p != end);
+ break;
+ }
+ default:
+ TRACE("Unhandled format %i, not adjusting volume.\n", stream->ss.format);
+ break;
+ }
+
+write:
+ return pa_stream_write(stream->stream, buffer, bytes, NULL, 0, PA_SEEK_RELATIVE);
+}
+
+static void pulse_write(struct pulse_stream *stream)
+{
+ /* write as much data to PA as we can */
+ UINT32 to_write;
+ BYTE *buf = stream->local_buffer + stream->pa_offs_bytes;
+ UINT32 bytes = pa_stream_writable_size(stream->stream);
+
+ if (stream->just_underran)
+ {
+ /* prebuffer with silence if needed */
+ if(stream->pa_held_bytes < bytes){
+ to_write = bytes - stream->pa_held_bytes;
+ TRACE("prebuffering %u frames of silence\n",
+ (int)(to_write / pa_frame_size(&stream->ss)));
+ buf = calloc(1, to_write);
+ pa_stream_write(stream->stream, buf, to_write, NULL, 0, PA_SEEK_RELATIVE);
+ free(buf);
+ }
+
+ stream->just_underran = FALSE;
+ }
+
+ buf = stream->local_buffer + stream->pa_offs_bytes;
+ TRACE("held: %lu, avail: %u\n", stream->pa_held_bytes, bytes);
+ bytes = min(stream->pa_held_bytes, bytes);
+
+ if (stream->pa_offs_bytes + bytes > stream->real_bufsize_bytes)
+ {
+ to_write = stream->real_bufsize_bytes - stream->pa_offs_bytes;
+ TRACE("writing small chunk of %u bytes\n", to_write);
+ write_buffer(stream, buf, to_write);
+ stream->pa_held_bytes -= to_write;
+ to_write = bytes - to_write;
+ stream->pa_offs_bytes = 0;
+ buf = stream->local_buffer;
+ }
+ else
+ to_write = bytes;
+
+ TRACE("writing main chunk of %u bytes\n", to_write);
+ write_buffer(stream, buf, to_write);
+ stream->pa_offs_bytes += to_write;
+ stream->pa_offs_bytes %= stream->real_bufsize_bytes;
+ stream->pa_held_bytes -= to_write;
+}
+
static void pulse_op_cb(pa_stream *s, int success, void *user)
{
TRACE("Success: %i\n", success);
@@ -277,11 +467,6 @@ static void pulse_op_cb(pa_stream *s, int success, void *user)
pulse_broadcast();
}
-static void silence_buffer(pa_sample_format_t format, BYTE *buffer, UINT32 bytes)
-{
- memset(buffer, format == PA_SAMPLE_U8 ? 0x80 : 0, bytes);
-}
-
static BOOL pulse_stream_valid(struct pulse_stream *stream)
{
return pa_stream_get_state(stream->stream) == PA_STREAM_READY;
@@ -958,191 +1143,6 @@ static NTSTATUS pulse_release_stream(void *args)
return STATUS_SUCCESS;
}
-static int write_buffer(const struct pulse_stream *stream, BYTE *buffer, UINT32 bytes)
-{
- const float *vol = stream->vol;
- UINT32 i, channels, mute = 0;
- BOOL adjust = FALSE;
- BYTE *end;
-
- if (!bytes) return 0;
-
- /* Adjust the buffer based on the volume for each channel */
- channels = stream->ss.channels;
- for (i = 0; i < channels; i++)
- {
- adjust |= vol[i] != 1.0f;
- if (vol[i] == 0.0f)
- mute++;
- }
- if (mute == channels)
- {
- silence_buffer(stream->ss.format, buffer, bytes);
- goto write;
- }
- if (!adjust) goto write;
-
- end = buffer + bytes;
- switch (stream->ss.format)
- {
-#ifndef WORDS_BIGENDIAN
-#define PROCESS_BUFFER(type) do \
-{ \
- type *p = (type*)buffer; \
- do \
- { \
- for (i = 0; i < channels; i++) \
- p[i] = p[i] * vol[i]; \
- p += i; \
- } while ((BYTE*)p != end); \
-} while (0)
- case PA_SAMPLE_S16LE:
- PROCESS_BUFFER(INT16);
- break;
- case PA_SAMPLE_S32LE:
- PROCESS_BUFFER(INT32);
- break;
- case PA_SAMPLE_FLOAT32LE:
- PROCESS_BUFFER(float);
- break;
-#undef PROCESS_BUFFER
- case PA_SAMPLE_S24_32LE:
- {
- UINT32 *p = (UINT32*)buffer;
- do
- {
- for (i = 0; i < channels; i++)
- {
- p[i] = (INT32)((INT32)(p[i] << 8) * vol[i]);
- p[i] >>= 8;
- }
- p += i;
- } while ((BYTE*)p != end);
- break;
- }
- case PA_SAMPLE_S24LE:
- {
- /* do it 12 bytes at a time until it is no longer possible */
- UINT32 *q = (UINT32*)buffer;
- BYTE *p;
-
- i = 0;
- while (end - (BYTE*)q >= 12)
- {
- UINT32 v[4], k;
- v[0] = q[0] << 8;
- v[1] = q[1] << 16 | (q[0] >> 16 & ~0xff);
- v[2] = q[2] << 24 | (q[1] >> 8 & ~0xff);
- v[3] = q[2] & ~0xff;
- for (k = 0; k < 4; k++)
- {
- v[k] = (INT32)((INT32)v[k] * vol[i]);
- if (++i == channels) i = 0;
- }
- *q++ = v[0] >> 8 | (v[1] & ~0xff) << 16;
- *q++ = v[1] >> 16 | (v[2] & ~0xff) << 8;
- *q++ = v[2] >> 24 | (v[3] & ~0xff);
- }
- p = (BYTE*)q;
- while (p != end)
- {
- UINT32 v = (INT32)((INT32)(p[0] << 8 | p[1] << 16 | p[2] << 24) * vol[i]);
- *p++ = v >> 8 & 0xff;
- *p++ = v >> 16 & 0xff;
- *p++ = v >> 24;
- if (++i == channels) i = 0;
- }
- break;
- }
-#endif
- case PA_SAMPLE_U8:
- {
- UINT8 *p = (UINT8*)buffer;
- do
- {
- for (i = 0; i < channels; i++)
- p[i] = (int)((p[i] - 128) * vol[i]) + 128;
- p += i;
- } while ((BYTE*)p != end);
- break;
- }
- case PA_SAMPLE_ALAW:
- {
- UINT8 *p = (UINT8*)buffer;
- do
- {
- for (i = 0; i < channels; i++)
- p[i] = mult_alaw_sample(p[i], vol[i]);
- p += i;
- } while ((BYTE*)p != end);
- break;
- }
- case PA_SAMPLE_ULAW:
- {
- UINT8 *p = (UINT8*)buffer;
- do
- {
- for (i = 0; i < channels; i++)
- p[i] = mult_ulaw_sample(p[i], vol[i]);
- p += i;
- } while ((BYTE*)p != end);
- break;
- }
- default:
- TRACE("Unhandled format %i, not adjusting volume.\n", stream->ss.format);
- break;
- }
-
-write:
- return pa_stream_write(stream->stream, buffer, bytes, NULL, 0, PA_SEEK_RELATIVE);
-}
-
-static void pulse_write(struct pulse_stream *stream)
-{
- /* write as much data to PA as we can */
- UINT32 to_write;
- BYTE *buf = stream->local_buffer + stream->pa_offs_bytes;
- UINT32 bytes = pa_stream_writable_size(stream->stream);
-
- if (stream->just_underran)
- {
- /* prebuffer with silence if needed */
- if(stream->pa_held_bytes < bytes){
- to_write = bytes - stream->pa_held_bytes;
- TRACE("prebuffering %u frames of silence\n",
- (int)(to_write / pa_frame_size(&stream->ss)));
- buf = calloc(1, to_write);
- pa_stream_write(stream->stream, buf, to_write, NULL, 0, PA_SEEK_RELATIVE);
- free(buf);
- }
-
- stream->just_underran = FALSE;
- }
-
- buf = stream->local_buffer + stream->pa_offs_bytes;
- TRACE("held: %lu, avail: %u\n", stream->pa_held_bytes, bytes);
- bytes = min(stream->pa_held_bytes, bytes);
-
- if (stream->pa_offs_bytes + bytes > stream->real_bufsize_bytes)
- {
- to_write = stream->real_bufsize_bytes - stream->pa_offs_bytes;
- TRACE("writing small chunk of %u bytes\n", to_write);
- write_buffer(stream, buf, to_write);
- stream->pa_held_bytes -= to_write;
- to_write = bytes - to_write;
- stream->pa_offs_bytes = 0;
- buf = stream->local_buffer;
- }
- else
- to_write = bytes;
-
- TRACE("writing main chunk of %u bytes\n", to_write);
- write_buffer(stream, buf, to_write);
- stream->pa_offs_bytes += to_write;
- stream->pa_offs_bytes %= stream->real_bufsize_bytes;
- stream->pa_held_bytes -= to_write;
-}
-
static void pulse_read(struct pulse_stream *stream)
{
size_t bytes = pa_stream_readable_size(stream->stream);
--
2.33.0
More information about the wine-devel
mailing list