Compare commits
5 Commits
a9151fdb86
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| d7269dd927 | |||
| ab859cdee1 | |||
| c1d1f7ae7c | |||
| 6bba1712ab | |||
| f95e4769b8 |
@@ -10,6 +10,17 @@ add_library(ao-play-async SHARED
|
|||||||
ao_playasync.h
|
ao_playasync.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
#include_directories(../../libao/include ../../libao/build-windows)
|
||||||
|
include_directories(windows)
|
||||||
|
target_link_directories(ao-play-async PRIVATE ../lib/windows-x86_64)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
target_link_libraries(ao-play-async PRIVATE libao-1.2.2 winmm.lib ksuser.lib)
|
||||||
|
else()
|
||||||
|
target_link_libraries(ao-play-async PRIVATE ao)
|
||||||
|
endif()
|
||||||
|
|
||||||
target_link_libraries(ao-play-async PRIVATE ao)
|
|
||||||
target_compile_definitions(ao-play-async PRIVATE AOPLAYASYNC_LIBRARY)
|
target_compile_definitions(ao-play-async PRIVATE AOPLAYASYNC_LIBRARY)
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,10 @@
|
|||||||
#ifdef USE_WINDOWS_THREADS
|
#ifdef USE_WINDOWS_THREADS
|
||||||
#define MUTEX_LOCK(m) WaitForSingleObject(m, INFINITE)
|
#define MUTEX_LOCK(m) WaitForSingleObject(m, INFINITE)
|
||||||
#define MUTEX_UNLOCK(m) ReleaseMutex(m)
|
#define MUTEX_UNLOCK(m) ReleaseMutex(m)
|
||||||
|
#define SEM_WAIT(sem, ms) (WaitForSingleObject(sem, ms) == WAIT_OBJECT_0)
|
||||||
|
#define SEM_TRYWAIT(sem) (WaitForSingleObject(sem, 0) == WAIT_OBJECT_0)
|
||||||
|
#define SEM_POST(sem) ReleaseSemaphore(sem, 1, NULL)
|
||||||
|
#define YIELD() sleep_ms(5)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_PTHREADS
|
#ifdef USE_PTHREADS
|
||||||
@@ -105,11 +109,18 @@ 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;
|
||||||
|
HANDLE clear_mutex;
|
||||||
HANDLE thread;
|
HANDLE thread;
|
||||||
DWORD thread_id;
|
DWORD thread_id;
|
||||||
|
HANDLE queue_sem;
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_PTHREADS
|
#ifdef USE_PTHREADS
|
||||||
pthread_mutex_t mutex;
|
pthread_mutex_t mutex;
|
||||||
@@ -122,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;
|
||||||
|
|
||||||
|
|
||||||
@@ -216,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
|
||||||
@@ -237,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 {
|
||||||
@@ -267,7 +333,11 @@ int ao_async_version()
|
|||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
static void at_exit_shutdown_ao(void)
|
||||||
|
#else
|
||||||
static void at_exit_shutdown_ao()
|
static void at_exit_shutdown_ao()
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
ao_shutdown();
|
ao_shutdown();
|
||||||
}
|
}
|
||||||
@@ -301,6 +371,12 @@ void *ao_create_async(int bits, int rate, int channels, int byte_format)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
@@ -328,8 +404,11 @@ void *ao_create_async(int bits, int rate, int channels, int byte_format)
|
|||||||
handle->pause_mutex = CreateMutex(NULL, // default security attributes
|
handle->pause_mutex = CreateMutex(NULL, // default security attributes
|
||||||
FALSE, // initially not owned
|
FALSE, // initially not owned
|
||||||
NULL);
|
NULL);
|
||||||
|
handle->clear_mutex = CreateMutex(NULL,
|
||||||
|
FALSE,
|
||||||
|
NULL);
|
||||||
|
handle->queue_sem = CreateSemaphore(NULL, 0, 1000000, NULL);
|
||||||
handle->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) run, handle, 0, &handle->thread_id);
|
handle->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) run, handle, 0, &handle->thread_id);
|
||||||
// TODO Windows Semaphores!
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
MUTEX_UNLOCK(handle->pause_mutex);
|
MUTEX_UNLOCK(handle->pause_mutex);
|
||||||
@@ -415,14 +494,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];
|
||||||
@@ -438,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
|
// 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;
|
||||||
@@ -451,7 +536,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];
|
||||||
}
|
}
|
||||||
@@ -544,6 +629,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;
|
||||||
@@ -565,3 +672,4 @@ void ao_pause_async(void *ao_handle, int paused)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
151
ao-play-async/windows/ao/ao.h
Normal file
151
ao-play-async/windows/ao/ao.h
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* ao.h
|
||||||
|
*
|
||||||
|
* Original Copyright (C) Aaron Holtzman - May 1999
|
||||||
|
* Modifications Copyright (C) Stan Seibert - July 2000, July 2001
|
||||||
|
* More Modifications Copyright (C) Jack Moffitt - October 2000
|
||||||
|
*
|
||||||
|
* This file is part of libao, a cross-platform audio outputlibrary. See
|
||||||
|
* README for a history of this source code.
|
||||||
|
*
|
||||||
|
* libao is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* libao is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Make; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef __AO_H__
|
||||||
|
#define __AO_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include "os_types.h"
|
||||||
|
|
||||||
|
/* --- Exporting functions ---*/
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#ifdef AO_BUILDING_LIBAO
|
||||||
|
#define AO_EXPORT __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
#define AO_EXPORT __declspec(dllimport)
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define AO_EXPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* --- Constants ---*/
|
||||||
|
|
||||||
|
#define AO_TYPE_LIVE 1
|
||||||
|
#define AO_TYPE_FILE 2
|
||||||
|
|
||||||
|
|
||||||
|
#define AO_ENODRIVER 1
|
||||||
|
#define AO_ENOTFILE 2
|
||||||
|
#define AO_ENOTLIVE 3
|
||||||
|
#define AO_EBADOPTION 4
|
||||||
|
#define AO_EOPENDEVICE 5
|
||||||
|
#define AO_EOPENFILE 6
|
||||||
|
#define AO_EFILEEXISTS 7
|
||||||
|
#define AO_EBADFORMAT 8
|
||||||
|
|
||||||
|
#define AO_EFAIL 100
|
||||||
|
|
||||||
|
|
||||||
|
#define AO_FMT_LITTLE 1
|
||||||
|
#define AO_FMT_BIG 2
|
||||||
|
#define AO_FMT_NATIVE 4
|
||||||
|
|
||||||
|
/* --- Structures --- */
|
||||||
|
|
||||||
|
typedef struct ao_info {
|
||||||
|
int type; /* live output or file output? */
|
||||||
|
char *name; /* full name of driver */
|
||||||
|
char *short_name; /* short name of driver */
|
||||||
|
char *author; /* driver author */
|
||||||
|
char *comment; /* driver comment */
|
||||||
|
int preferred_byte_format;
|
||||||
|
int priority;
|
||||||
|
char **options;
|
||||||
|
int option_count;
|
||||||
|
} ao_info;
|
||||||
|
|
||||||
|
typedef struct ao_functions ao_functions;
|
||||||
|
typedef struct ao_device ao_device;
|
||||||
|
|
||||||
|
typedef struct ao_sample_format {
|
||||||
|
int bits; /* bits per sample */
|
||||||
|
int rate; /* samples per second (in a single channel) */
|
||||||
|
int channels; /* number of audio channels */
|
||||||
|
int byte_format; /* Byte ordering in sample, see constants below */
|
||||||
|
char *matrix; /* input channel location/ordering */
|
||||||
|
} ao_sample_format;
|
||||||
|
|
||||||
|
typedef struct ao_option {
|
||||||
|
char *key;
|
||||||
|
char *value;
|
||||||
|
struct ao_option *next;
|
||||||
|
} ao_option;
|
||||||
|
|
||||||
|
#if defined(AO_BUILDING_LIBAO)
|
||||||
|
#include "ao_private.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* --- Functions --- */
|
||||||
|
|
||||||
|
/* library setup/teardown */
|
||||||
|
AO_EXPORT void ao_initialize(void);
|
||||||
|
AO_EXPORT void ao_shutdown(void);
|
||||||
|
|
||||||
|
/* device setup/playback/teardown */
|
||||||
|
AO_EXPORT int ao_append_global_option(const char *key,
|
||||||
|
const char *value);
|
||||||
|
AO_EXPORT int ao_append_option(ao_option **options,
|
||||||
|
const char *key,
|
||||||
|
const char *value);
|
||||||
|
AO_EXPORT void ao_free_options(ao_option *options);
|
||||||
|
AO_EXPORT ao_device* ao_open_live(int driver_id,
|
||||||
|
ao_sample_format *format,
|
||||||
|
ao_option *option);
|
||||||
|
AO_EXPORT ao_device* ao_open_file(int driver_id,
|
||||||
|
const char *filename,
|
||||||
|
int overwrite,
|
||||||
|
ao_sample_format *format,
|
||||||
|
ao_option *option);
|
||||||
|
|
||||||
|
AO_EXPORT int ao_play(ao_device *device,
|
||||||
|
char *output_samples,
|
||||||
|
uint_32 num_bytes);
|
||||||
|
AO_EXPORT int ao_close(ao_device *device);
|
||||||
|
|
||||||
|
/* driver information */
|
||||||
|
AO_EXPORT int ao_driver_id(const char *short_name);
|
||||||
|
AO_EXPORT int ao_default_driver_id(void);
|
||||||
|
AO_EXPORT ao_info *ao_driver_info(int driver_id);
|
||||||
|
AO_EXPORT ao_info **ao_driver_info_list(int *driver_count);
|
||||||
|
AO_EXPORT const char *ao_file_extension(int driver_id);
|
||||||
|
|
||||||
|
/* miscellaneous */
|
||||||
|
AO_EXPORT int ao_is_big_endian(void);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#endif /* __AO_H__ */
|
||||||
10
ao-play-async/windows/ao/os_types.h
Normal file
10
ao-play-async/windows/ao/os_types.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef uint8_t uint_8;
|
||||||
|
typedef uint16_t uint_16;
|
||||||
|
typedef uint32_t uint_32;
|
||||||
|
typedef int8_t sint_8;
|
||||||
|
typedef int16_t sint_16;
|
||||||
|
typedef int32_t sint_32;
|
||||||
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
lib/windows-x86_64/ao-play-async.lib
Normal file
BIN
lib/windows-x86_64/ao-play-async.lib
Normal file
Binary file not shown.
BIN
lib/windows-x86_64/libao-1.2.2.dll
Normal file
BIN
lib/windows-x86_64/libao-1.2.2.dll
Normal file
Binary file not shown.
BIN
lib/windows-x86_64/libao-1.2.2.lib
Normal file
BIN
lib/windows-x86_64/libao-1.2.2.lib
Normal file
Binary file not shown.
Binary file not shown.
BIN
lib/windows-x86_64/libao-static-1.2.2.lib
Normal file
BIN
lib/windows-x86_64/libao-static-1.2.2.lib
Normal file
Binary file not shown.
Reference in New Issue
Block a user