adjusting volume and getting current volume.
This commit is contained in:
@@ -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 {
|
||||
@@ -311,6 +371,12 @@ void *ao_create_async(int bits, int rate, int channels, int byte_format)
|
||||
}
|
||||
|
||||
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 +494,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 +518,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 +536,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 +629,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 +672,4 @@ void ao_pause_async(void *ao_handle, int paused)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user