Compare commits
10 Commits
6bba1712ab
..
0-1-2
| Author | SHA1 | Date | |
|---|---|---|---|
| 7a34caf066 | |||
| 28854a6a38 | |||
| cefbbeb41d | |||
| f14089b153 | |||
| 348b1d6411 | |||
| ee7e62890f | |||
| b02ac26bd5 | |||
| d7269dd927 | |||
| ab859cdee1 | |||
| c1d1f7ae7c |
@@ -16,4 +16,7 @@
|
|||||||
*.mod
|
*.mod
|
||||||
*.smod
|
*.smod
|
||||||
|
|
||||||
|
build
|
||||||
|
lib/linux-x86_64
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -109,6 +109,11 @@ typedef struct {
|
|||||||
int paused;
|
int paused;
|
||||||
|
|
||||||
ao_device *ao_device;
|
ao_device *ao_device;
|
||||||
|
int dev_bits_per_sample;
|
||||||
|
int dev_endianess;
|
||||||
|
int dev_channels;
|
||||||
|
int dev_rate;
|
||||||
|
|
||||||
#ifdef USE_WINDOWS_THREADS
|
#ifdef USE_WINDOWS_THREADS
|
||||||
HANDLE mutex;
|
HANDLE mutex;
|
||||||
HANDLE pause_mutex;
|
HANDLE pause_mutex;
|
||||||
@@ -128,6 +133,7 @@ typedef struct {
|
|||||||
double music_duration;
|
double music_duration;
|
||||||
int at_music_id;
|
int at_music_id;
|
||||||
int buf_size;
|
int buf_size;
|
||||||
|
int volume_in_10000; // volume in 100000 steps, i.e. 100000 equals 100%
|
||||||
} AO_Handle;
|
} AO_Handle;
|
||||||
|
|
||||||
|
|
||||||
@@ -222,6 +228,55 @@ static void clear(AO_Handle *h)
|
|||||||
MUTEX_UNLOCK(h->clear_mutex);
|
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
|
#ifdef USE_PTHREADS
|
||||||
static void *run(void *arg)
|
static void *run(void *arg)
|
||||||
#endif
|
#endif
|
||||||
@@ -243,6 +298,11 @@ static DWORD run(LPVOID arg)
|
|||||||
handle->music_duration = q->music_duration;
|
handle->music_duration = q->music_duration;
|
||||||
handle->at_music_id = q->music_id;
|
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) {
|
if (q->command == STOP) {
|
||||||
go_on = (1 == 0);
|
go_on = (1 == 0);
|
||||||
} else {
|
} 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();
|
init_ao();
|
||||||
|
|
||||||
@@ -304,13 +364,26 @@ void *ao_create_async(int bits, int rate, int channels, int byte_format)
|
|||||||
fmt.channels = channels;
|
fmt.channels = channels;
|
||||||
fmt.matrix = NULL;
|
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) {
|
if (dev == NULL) {
|
||||||
fprintf(stderr, "Cannot open ao-device, error code = %d\n", errno);
|
fprintf(stderr, "Cannot open ao-device, error code = %d\n", errno);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
handle->ao_device = dev;
|
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->play_queue = NULL;
|
||||||
handle->last_frame = NULL;
|
handle->last_frame = NULL;
|
||||||
handle->at_second = -1;
|
handle->at_second = -1;
|
||||||
@@ -428,14 +501,15 @@ void ao_stop_async(void *ao_handle)
|
|||||||
#define AO_FMT_BIG 2
|
#define AO_FMT_BIG 2
|
||||||
#define AO_FMT_NATIVE 4
|
#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;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < bytes_per_sample; i++) {
|
for (i = 0; i < bytes_per_sample; i++) {
|
||||||
b[i] = sample&0xff;
|
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 };
|
unsigned char b1[4] = { 0, 0, 0, 0 };
|
||||||
for(i = 0; i < bytes_per_sample; i++) {
|
for(i = 0; i < bytes_per_sample; i++) {
|
||||||
b1[bytes_per_sample - i - 1] = b[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
|
// 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 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;
|
int store_size = info->channels * bytes * buf_len;
|
||||||
unsigned char *new_mem = (unsigned char *) malloc(store_size);
|
unsigned char *new_mem = (unsigned char *) malloc(store_size);
|
||||||
*audio_size = 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 *chan = buffer[channel];
|
||||||
int32_t sample = chan[k];
|
int32_t sample = chan[k];
|
||||||
unsigned char b[4];
|
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++) {
|
for(int j = 0; j < bytes; j++) {
|
||||||
new_mem[i++] = b[j];
|
new_mem[i++] = b[j];
|
||||||
}
|
}
|
||||||
@@ -557,6 +636,28 @@ int ao_bufsize_async(void *ao_handle)
|
|||||||
return s;
|
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)
|
void ao_pause_async(void *ao_handle, int paused)
|
||||||
{
|
{
|
||||||
AO_Handle *h = (AO_Handle *) ao_handle;
|
AO_Handle *h = (AO_Handle *) ao_handle;
|
||||||
@@ -578,3 +679,4 @@ void ao_pause_async(void *ao_handle, int paused)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ typedef struct {
|
|||||||
} BufferInfo_t;
|
} BufferInfo_t;
|
||||||
|
|
||||||
AOPLAYASYNC_EXPORT int ao_async_version(void);
|
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_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_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);
|
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_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);
|
AOPLAYASYNC_EXPORT int ao_bufsize_async(void *handle);
|
||||||
|
|
||||||
#endif // AO_PLAYASYNC_H
|
#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.
Reference in New Issue
Block a user