10 Commits

Author SHA1 Message Date
hans 7a34caf066 - 2026-04-23 11:23:07 +02:00
hans 28854a6a38 - 2026-04-23 11:22:36 +02:00
hans cefbbeb41d - 2026-04-23 11:20:48 +02:00
hans f14089b153 - 2026-04-23 11:16:04 +02:00
hans 348b1d6411 Trying to overcome gapless problems with mpg123 + output to WAV 2026-04-23 11:03:02 +02:00
hans ee7e62890f mpg123 support 2026-04-22 08:50:44 +02:00
hans b02ac26bd5 audio decoding 2026-04-21 22:53:25 +02:00
hans d7269dd927 adjusting volume and getting current volume. 2026-04-21 09:57:42 +02:00
hans ab859cdee1 Small bug fix. 2026-04-17 13:57:09 +02:00
hans c1d1f7ae7c small adjustments, many enhancements to rktplayer 2026-04-16 22:22:24 +02:00
11 changed files with 118 additions and 8 deletions
+3
View File
@@ -16,4 +16,7 @@
*.mod
*.smod
build
lib/linux-x86_64
+2
View File
@@ -24,3 +24,5 @@ zip: install
clean:
rm -rf build
+109 -7
View File
@@ -109,6 +109,11 @@ typedef struct {
int paused;
ao_device *ao_device;
int dev_bits_per_sample;
int dev_endianess;
int dev_channels;
int dev_rate;
#ifdef USE_WINDOWS_THREADS
HANDLE mutex;
HANDLE pause_mutex;
@@ -128,6 +133,7 @@ typedef struct {
double music_duration;
int at_music_id;
int buf_size;
int volume_in_10000; // volume in 100000 steps, i.e. 100000 equals 100%
} AO_Handle;
@@ -222,6 +228,55 @@ static void clear(AO_Handle *h)
MUTEX_UNLOCK(h->clear_mutex);
}
static int inline littleEndian()
{
int n = 1;
return (*(char *)&n) == 1;
}
static void inline adjustVolume(AO_Handle *handle, char *_buf, int buf_size, int volume_in_10000)
{
int bytes_per_sample = (handle->dev_bits_per_sample >> 3);
register int endianess = handle->dev_endianess;
register unsigned char *buf = (unsigned char *) _buf;
register int i;
register long long sample;
register int k;
int little_endian = (endianess == AO_FMT_LITTLE);
if (!little_endian && endianess == AO_FMT_NATIVE) little_endian = littleEndian();
for(i = 0; i < buf_size; i += bytes_per_sample) {
if (little_endian) {
sample = buf[bytes_per_sample + i - 1] > 127 ? -1 : 0;
for(k = bytes_per_sample + i - 1; k >= i; k--) {
sample <<= 8;
sample |= buf[k];
}
} else {
sample = (buf[i] > 127) ? -1 : 0;
for(k = i; k < (i + bytes_per_sample); k++) {
sample <<= 8;
sample += buf[k];
}
}
sample *= volume_in_10000;
sample /= 10000;
if (little_endian) {
for(k = i; k < (i + bytes_per_sample); k++) {
buf[k] = sample&0xff;
sample >>= 8;
}
} else {
for(k = i + bytes_per_sample - 1; k >= i; k--) {
buf[k] = sample&0xff;
sample >>= 8;
}
}
}
}
#ifdef USE_PTHREADS
static void *run(void *arg)
#endif
@@ -243,6 +298,11 @@ static DWORD run(LPVOID arg)
handle->music_duration = q->music_duration;
handle->at_music_id = q->music_id;
if (handle->volume_in_10000 != 10000) {
// adjust volume
adjustVolume(handle, q->buf, q->buflen, handle->volume_in_10000);
}
if (q->command == STOP) {
go_on = (1 == 0);
} else {
@@ -291,7 +351,7 @@ static void init_ao()
}
}
void *ao_create_async(int bits, int rate, int channels, int byte_format)
void *ao_create_async(int bits, int rate, int channels, int byte_format, const char *wav_file_output)
{
init_ao();
@@ -304,13 +364,26 @@ void *ao_create_async(int bits, int rate, int channels, int byte_format)
fmt.channels = channels;
fmt.matrix = NULL;
ao_device *dev = ao_open_live(ao_default_driver_id(), &fmt, NULL);
ao_device *dev;
if (wav_file_output != NULL) {
int driver_id = ao_driver_id("wav");
dev = ao_open_file(driver_id, wav_file_output, 1, &fmt, NULL);
} else {
dev = ao_open_live(ao_default_driver_id(), &fmt, NULL);
}
if (dev == NULL) {
fprintf(stderr, "Cannot open ao-device, error code = %d\n", errno);
return NULL;
}
handle->ao_device = dev;
handle->dev_bits_per_sample = bits;
handle->dev_channels = channels;
handle->dev_rate = rate;
handle->dev_endianess = byte_format;
handle->volume_in_10000 = 10000;
handle->play_queue = NULL;
handle->last_frame = NULL;
handle->at_second = -1;
@@ -428,14 +501,15 @@ void ao_stop_async(void *ao_handle)
#define AO_FMT_BIG 2
#define AO_FMT_NATIVE 4
static inline void make_sample_bytes(int32_t sample, int bytes_per_sample, int endianess, unsigned char b[4])
static inline void make_sample_bytes(int32_t sample, int bytes_per_sample, int big_endian, unsigned char b[4])
{
int i;
for (i = 0; i < bytes_per_sample; i++) {
b[i] = sample&0xff;
sample = sample >> 8;
sample >>= 8;
}
if (endianess == AO_FMT_BIG) {
if (big_endian) {
unsigned char b1[4] = { 0, 0, 0, 0 };
for(i = 0; i < bytes_per_sample; i++) {
b1[bytes_per_sample - i - 1] = b[i];
@@ -451,7 +525,12 @@ void *convertFlac(void *mem, int buf_len, BufferInfo_t *info, int *audio_size)
// buf_size equals number of samples of 32bit for all channels. So buf_size for flac = 4 * buf_len * channels
int bytes = info->sample_bits / 8;
int endianness = info->endiannes;
int endianess = info->endiannes;
int little_endian = (endianess == AO_FMT_LITTLE);
if (!little_endian && endianess == AO_FMT_NATIVE) little_endian = littleEndian();
int big_endian = !little_endian;
int store_size = info->channels * bytes * buf_len;
unsigned char *new_mem = (unsigned char *) malloc(store_size);
*audio_size = store_size;
@@ -464,7 +543,7 @@ void *convertFlac(void *mem, int buf_len, BufferInfo_t *info, int *audio_size)
int32_t *chan = buffer[channel];
int32_t sample = chan[k];
unsigned char b[4];
make_sample_bytes(sample, bytes, endianness, b);
make_sample_bytes(sample, bytes, big_endian, b);
for(int j = 0; j < bytes; j++) {
new_mem[i++] = b[j];
}
@@ -557,6 +636,28 @@ int ao_bufsize_async(void *ao_handle)
return s;
}
void ao_set_volume_async(void *ao_handle, double percentage)
{
AO_Handle *h = (AO_Handle *) ao_handle;
MUTEX_LOCK(h->mutex);
int volume_10000 = (int) (percentage * 100.0);
if (volume_10000 >= 9990 && volume_10000 <= 10010) {
volume_10000 = 10000;
}
h->volume_in_10000 = volume_10000;
MUTEX_UNLOCK(h->mutex);
}
double ao_volume_async(void *ao_handle)
{
AO_Handle *h = (AO_Handle *) ao_handle;
MUTEX_LOCK(h->mutex);
double volume = h->volume_in_10000 / 100.0;
MUTEX_UNLOCK(h->mutex);
return volume;
}
void ao_pause_async(void *ao_handle, int paused)
{
AO_Handle *h = (AO_Handle *) ao_handle;
@@ -578,3 +679,4 @@ void ao_pause_async(void *ao_handle, int paused)
}
+4 -1
View File
@@ -29,7 +29,7 @@ typedef struct {
} BufferInfo_t;
AOPLAYASYNC_EXPORT int ao_async_version(void);
AOPLAYASYNC_EXPORT void *ao_create_async(int bits, int rate, int channels, int byte_format);
AOPLAYASYNC_EXPORT void *ao_create_async(int bits, int rate, int channels, int byte_format, const char *wav_file_output);
AOPLAYASYNC_EXPORT void ao_stop_async(void *handle);
AOPLAYASYNC_EXPORT void ao_play_async(void *handle, int music_id, double at_second, double music_duration, int buf_size, void *mem, BufferInfo_t info);
AOPLAYASYNC_EXPORT void ao_clear_async(void *handle);
@@ -40,6 +40,9 @@ AOPLAYASYNC_EXPORT double ao_music_duration_async(void *handle);
AOPLAYASYNC_EXPORT void ao_pause_async(void *ao_handle, int paused);
AOPLAYASYNC_EXPORT void ao_set_volume_async(void *ao_handle, double percentage);
AOPLAYASYNC_EXPORT double ao_volume_async(void *ao_handle);
AOPLAYASYNC_EXPORT int ao_bufsize_async(void *handle);
#endif // AO_PLAYASYNC_H
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.