mirror of
https://github.com/mpv-player/mpv
synced 2025-01-11 17:39:38 +00:00
fixed, strengthened, rewrote, and renamed a variety of the ADPCM decoders
(including MS, DK4 and DK3 ADPCM) git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@4855 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
parent
3605aa4ec8
commit
ba4694f4bb
251
adpcm.c
251
adpcm.c
@ -12,6 +12,7 @@
|
||||
#include "config.h"
|
||||
#include "bswap.h"
|
||||
#include "adpcm.h"
|
||||
#include "mp_msg.h"
|
||||
|
||||
#define BE_16(x) (be2me_16(*(unsigned short *)(x)))
|
||||
#define BE_32(x) (be2me_32(*(unsigned int *)(x)))
|
||||
@ -196,11 +197,19 @@ int ms_adpcm_decode_block(unsigned short *output, unsigned char *input,
|
||||
int predictor;
|
||||
|
||||
// fetch the header information, in stereo if both channels are present
|
||||
if (input[stream_ptr] > 6)
|
||||
mp_msg(MSGT_DECAUDIO, MSGL_WARN,
|
||||
"MS ADPCM: coefficient (%d) out of range (should be [0..6])\n",
|
||||
input[stream_ptr]);
|
||||
coeff1[0] = ms_adapt_coeff1[input[stream_ptr]];
|
||||
coeff2[0] = ms_adapt_coeff2[input[stream_ptr]];
|
||||
stream_ptr++;
|
||||
if (channels == 2)
|
||||
{
|
||||
if (input[stream_ptr] > 6)
|
||||
mp_msg(MSGT_DECAUDIO, MSGL_WARN,
|
||||
"MS ADPCM: coefficient (%d) out of range (should be [0..6])\n",
|
||||
input[stream_ptr]);
|
||||
coeff1[1] = ms_adapt_coeff1[input[stream_ptr]];
|
||||
coeff2[1] = ms_adapt_coeff2[input[stream_ptr]];
|
||||
stream_ptr++;
|
||||
@ -267,49 +276,71 @@ int ms_adpcm_decode_block(unsigned short *output, unsigned char *input,
|
||||
return (block_size - (MS_ADPCM_PREAMBLE_SIZE * channels)) * 2;
|
||||
}
|
||||
|
||||
// note: This decoder assumes the format 0x61 data always comes in
|
||||
// mono flavor
|
||||
int fox61_adpcm_decode_block(unsigned short *output, unsigned char *input)
|
||||
int dk4_adpcm_decode_block(unsigned short *output, unsigned char *input,
|
||||
int channels, int block_size)
|
||||
{
|
||||
int i;
|
||||
int predictor;
|
||||
int index;
|
||||
int output_ptr;
|
||||
int predictor_l = 0;
|
||||
int predictor_r = 0;
|
||||
int index_l = 0;
|
||||
int index_r = 0;
|
||||
|
||||
// the first predictor value goes straight to the output
|
||||
predictor = output[0] = LE_16(&input[0]);
|
||||
SE_16BIT(predictor);
|
||||
index = input[2];
|
||||
|
||||
// unpack the nibbles
|
||||
for (i = 4; i < FOX61_ADPCM_BLOCK_SIZE; i++)
|
||||
predictor_l = output[0] = LE_16(&input[0]);
|
||||
SE_16BIT(predictor_l);
|
||||
index_l = input[2];
|
||||
if (channels == 2)
|
||||
{
|
||||
output[1 + (i - 4) * 2 + 0] = (input[i] >> 4) & 0x0F;
|
||||
output[1 + (i - 4) * 2 + 1] = input[i] & 0x0F;
|
||||
predictor_r = output[1] = LE_16(&input[4]);
|
||||
SE_16BIT(predictor_r);
|
||||
index_r = input[6];
|
||||
}
|
||||
|
||||
decode_nibbles(&output[1], FOX61_ADPCM_SAMPLES_PER_BLOCK - 1, 1,
|
||||
predictor, index,
|
||||
0, 0);
|
||||
output_ptr = channels;
|
||||
for (i = DK4_ADPCM_PREAMBLE_SIZE * channels; i < block_size; i++)
|
||||
{
|
||||
output[output_ptr++] = input[i] >> 4;
|
||||
output[output_ptr++] = input[i] & 0x0F;
|
||||
}
|
||||
|
||||
return FOX61_ADPCM_SAMPLES_PER_BLOCK;
|
||||
decode_nibbles(&output[channels],
|
||||
(block_size - DK4_ADPCM_PREAMBLE_SIZE * channels) * 2 - channels,
|
||||
channels,
|
||||
predictor_l, index_l,
|
||||
predictor_r, index_r);
|
||||
|
||||
return (block_size - DK4_ADPCM_PREAMBLE_SIZE * channels) * 2 - channels;
|
||||
}
|
||||
|
||||
#define DK3_GET_NEXT_NIBBLE() \
|
||||
if (decode_top_nibble_next) \
|
||||
{ \
|
||||
nibble = (last_byte >> 4) & 0x0F; \
|
||||
decode_top_nibble_next = 0; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
last_byte = input[in_ptr++]; \
|
||||
nibble = last_byte & 0x0F; \
|
||||
decode_top_nibble_next = 1; \
|
||||
}
|
||||
|
||||
// note: This decoder assumes the format 0x62 data always comes in
|
||||
// stereo flavor
|
||||
int fox62_adpcm_decode_block(unsigned short *output, unsigned char *input)
|
||||
int dk3_adpcm_decode_block(unsigned short *output, unsigned char *input)
|
||||
{
|
||||
int pred1;
|
||||
int pred2;
|
||||
int index1;
|
||||
int index2;
|
||||
int sum_pred;
|
||||
int diff_pred;
|
||||
int sum_index;
|
||||
int diff_index;
|
||||
int diff_channel;
|
||||
int in_ptr = 0x10;
|
||||
int out_ptr = 0;
|
||||
|
||||
int flag1 = 0;
|
||||
int flag2 = 1;
|
||||
int sum;
|
||||
unsigned char last_byte = 0;
|
||||
unsigned char nibble;
|
||||
int decode_top_nibble_next = 0;
|
||||
|
||||
// ADPCM work variables
|
||||
int sign;
|
||||
@ -317,137 +348,93 @@ int fox62_adpcm_decode_block(unsigned short *output, unsigned char *input)
|
||||
int step;
|
||||
int diff;
|
||||
|
||||
pred1 = LE_16(&input[10]);
|
||||
pred2 = LE_16(&input[12]);
|
||||
SE_16BIT(pred1);
|
||||
SE_16BIT(pred2);
|
||||
sum = pred2;
|
||||
index1 = input[14];
|
||||
index2 = input[15];
|
||||
sum_pred = LE_16(&input[10]);
|
||||
diff_pred = LE_16(&input[12]);
|
||||
SE_16BIT(sum_pred);
|
||||
SE_16BIT(diff_pred);
|
||||
diff_channel = diff_pred;
|
||||
sum_index = input[14];
|
||||
diff_index = input[15];
|
||||
|
||||
while (in_ptr < 2048)
|
||||
{
|
||||
if (flag2)
|
||||
{
|
||||
last_byte = input[in_ptr++];
|
||||
nibble = last_byte & 0x0F;
|
||||
// process the first predictor of the sum channel
|
||||
DK3_GET_NEXT_NIBBLE();
|
||||
|
||||
step = adpcm_step[index1];
|
||||
step = adpcm_step[sum_index];
|
||||
|
||||
sign = nibble & 8;
|
||||
delta = nibble & 7;
|
||||
sign = nibble & 8;
|
||||
delta = nibble & 7;
|
||||
|
||||
diff = step >> 3;
|
||||
if (delta & 4) diff += step;
|
||||
if (delta & 2) diff += step >> 1;
|
||||
if (delta & 1) diff += step >> 2;
|
||||
diff = step >> 3;
|
||||
if (delta & 4) diff += step;
|
||||
if (delta & 2) diff += step >> 1;
|
||||
if (delta & 1) diff += step >> 2;
|
||||
|
||||
if (sign)
|
||||
pred1 -= diff;
|
||||
else
|
||||
pred1 += diff;
|
||||
|
||||
CLAMP_S16(pred1);
|
||||
|
||||
index1 += adpcm_index[nibble];
|
||||
CLAMP_0_TO_88(index1);
|
||||
|
||||
if (flag1)
|
||||
flag2 = 0;
|
||||
else
|
||||
{
|
||||
nibble = (last_byte >> 4) & 0x0F;
|
||||
|
||||
step = adpcm_step[index2];
|
||||
|
||||
sign = nibble & 8;
|
||||
delta = nibble & 7;
|
||||
|
||||
diff = step >> 3;
|
||||
if (delta & 4) diff += step;
|
||||
if (delta & 2) diff += step >> 1;
|
||||
if (delta & 1) diff += step >> 2;
|
||||
|
||||
if (sign)
|
||||
pred2 -= diff;
|
||||
else
|
||||
pred2 += diff;
|
||||
|
||||
CLAMP_S16(pred2);
|
||||
|
||||
index2 += adpcm_index[nibble];
|
||||
CLAMP_0_TO_88(index2);
|
||||
|
||||
sum = (sum + pred2) / 2;
|
||||
}
|
||||
output[out_ptr++] = pred1 + sum;
|
||||
output[out_ptr++] = pred1 - sum;
|
||||
|
||||
flag1 ^= 1;
|
||||
if (in_ptr >= 2048)
|
||||
break;
|
||||
}
|
||||
if (sign)
|
||||
sum_pred -= diff;
|
||||
else
|
||||
{
|
||||
nibble = (last_byte >> 4) & 0x0F;
|
||||
sum_pred += diff;
|
||||
|
||||
step = adpcm_step[index1];
|
||||
CLAMP_S16(sum_pred);
|
||||
|
||||
sign = nibble & 8;
|
||||
delta = nibble & 7;
|
||||
sum_index += adpcm_index[nibble];
|
||||
CLAMP_0_TO_88(sum_index);
|
||||
|
||||
// process the diff channel predictor
|
||||
DK3_GET_NEXT_NIBBLE();
|
||||
|
||||
diff = step >> 3;
|
||||
if (delta & 4) diff += step;
|
||||
if (delta & 2) diff += step >> 1;
|
||||
if (delta & 1) diff += step >> 2;
|
||||
step = adpcm_step[diff_index];
|
||||
|
||||
if (sign)
|
||||
pred1 -= diff;
|
||||
else
|
||||
pred1 += diff;
|
||||
sign = nibble & 8;
|
||||
delta = nibble & 7;
|
||||
|
||||
CLAMP_S16(pred1);
|
||||
diff = step >> 3;
|
||||
if (delta & 4) diff += step;
|
||||
if (delta & 2) diff += step >> 1;
|
||||
if (delta & 1) diff += step >> 2;
|
||||
|
||||
index1 += adpcm_index[nibble];
|
||||
CLAMP_0_TO_88(index1);
|
||||
if (sign)
|
||||
diff_pred -= diff;
|
||||
else
|
||||
diff_pred += diff;
|
||||
|
||||
if (flag1)
|
||||
flag2 = 1;
|
||||
else
|
||||
{
|
||||
last_byte = input[in_ptr++];
|
||||
nibble = last_byte & 0x0F;
|
||||
CLAMP_S16(diff_pred);
|
||||
|
||||
step = adpcm_step[index2];
|
||||
diff_index += adpcm_index[nibble];
|
||||
CLAMP_0_TO_88(diff_index);
|
||||
|
||||
sign = nibble & 8;
|
||||
delta = nibble & 7;
|
||||
// output the first pair of stereo PCM samples
|
||||
diff_channel = (diff_channel + diff_pred) / 2;
|
||||
output[out_ptr++] = sum_pred + diff_channel;
|
||||
output[out_ptr++] = sum_pred - diff_channel;
|
||||
|
||||
diff = step >> 3;
|
||||
if (delta & 4) diff += step;
|
||||
if (delta & 2) diff += step >> 1;
|
||||
if (delta & 1) diff += step >> 2;
|
||||
// process the second predictor of the sum channel
|
||||
DK3_GET_NEXT_NIBBLE();
|
||||
|
||||
if (sign)
|
||||
pred2 -= diff;
|
||||
else
|
||||
pred2 += diff;
|
||||
step = adpcm_step[sum_index];
|
||||
|
||||
CLAMP_S16(pred2);
|
||||
sign = nibble & 8;
|
||||
delta = nibble & 7;
|
||||
|
||||
index2 += adpcm_index[nibble];
|
||||
CLAMP_0_TO_88(index2);
|
||||
diff = step >> 3;
|
||||
if (delta & 4) diff += step;
|
||||
if (delta & 2) diff += step >> 1;
|
||||
if (delta & 1) diff += step >> 2;
|
||||
|
||||
sum = (sum + pred2) / 2;
|
||||
}
|
||||
if (sign)
|
||||
sum_pred -= diff;
|
||||
else
|
||||
sum_pred += diff;
|
||||
|
||||
output[out_ptr++] = pred1 + sum;
|
||||
output[out_ptr++] = pred1 - sum;
|
||||
CLAMP_S16(sum_pred);
|
||||
|
||||
flag1 ^= 1;
|
||||
if (in_ptr >= 2048)
|
||||
break;
|
||||
}
|
||||
sum_index += adpcm_index[nibble];
|
||||
CLAMP_0_TO_88(sum_index);
|
||||
|
||||
// output the second pair of stereo PCM samples
|
||||
output[out_ptr++] = sum_pred + diff_channel;
|
||||
output[out_ptr++] = sum_pred - diff_channel;
|
||||
}
|
||||
|
||||
return out_ptr;
|
||||
|
19
adpcm.h
19
adpcm.h
@ -10,21 +10,22 @@
|
||||
#define MS_ADPCM_SAMPLES_PER_BLOCK \
|
||||
((sh_audio->wf->nBlockAlign - MS_ADPCM_PREAMBLE_SIZE) * 2)
|
||||
|
||||
#define FOX61_ADPCM_PREAMBLE_SIZE 4
|
||||
#define FOX61_ADPCM_BLOCK_SIZE 0x200
|
||||
#define FOX61_ADPCM_SAMPLES_PER_BLOCK \
|
||||
(((FOX61_ADPCM_BLOCK_SIZE - FOX61_ADPCM_PREAMBLE_SIZE) * 2) + 1)
|
||||
#define DK4_ADPCM_PREAMBLE_SIZE 4
|
||||
#define DK4_ADPCM_SAMPLES_PER_BLOCK \
|
||||
(((sh_audio->wf->nBlockAlign - DK4_ADPCM_PREAMBLE_SIZE) * 2) + 1)
|
||||
|
||||
// pretend there's such a thing as mono for this format
|
||||
#define FOX62_ADPCM_PREAMBLE_SIZE 8
|
||||
#define FOX62_ADPCM_BLOCK_SIZE 0x400
|
||||
#define DK3_ADPCM_PREAMBLE_SIZE 8
|
||||
#define DK3_ADPCM_BLOCK_SIZE 0x400
|
||||
// this isn't exact
|
||||
#define FOX62_ADPCM_SAMPLES_PER_BLOCK 6000
|
||||
#define DK3_ADPCM_SAMPLES_PER_BLOCK 6000
|
||||
|
||||
int ima_adpcm_decode_block(unsigned short *output, unsigned char *input,
|
||||
int channels);
|
||||
int ms_adpcm_decode_block(unsigned short *output, unsigned char *input,
|
||||
int channels, int block_size);
|
||||
int fox61_adpcm_decode_block(unsigned short *output, unsigned char *input);
|
||||
int fox62_adpcm_decode_block(unsigned short *output, unsigned char *input);
|
||||
int dk4_adpcm_decode_block(unsigned short *output, unsigned char *input,
|
||||
int channels, int block_size);
|
||||
int dk3_adpcm_decode_block(unsigned short *output, unsigned char *input);
|
||||
|
||||
#endif
|
||||
|
@ -224,8 +224,8 @@ static short get_driver(char *s,int audioflag)
|
||||
"liba52",
|
||||
"g72x",
|
||||
"imaadpcm",
|
||||
"fox61adpcm",
|
||||
"fox62adpcm",
|
||||
"dk4adpcm",
|
||||
"dk3adpcm",
|
||||
"roqaudio",
|
||||
NULL
|
||||
};
|
||||
|
@ -35,8 +35,8 @@
|
||||
#define AFM_A52 14
|
||||
#define AFM_G72X 15
|
||||
#define AFM_IMAADPCM 16
|
||||
#define AFM_FOX61ADPCM 17
|
||||
#define AFM_FOX62ADPCM 18
|
||||
#define AFM_DK4ADPCM 17
|
||||
#define AFM_DK3ADPCM 18
|
||||
#define AFM_ROQAUDIO 19
|
||||
|
||||
#define VFM_MPEG 1
|
||||
|
55
dec_audio.c
55
dec_audio.c
@ -425,21 +425,21 @@ case AFM_MSADPCM:
|
||||
sh_audio->ds->ss_div = MS_ADPCM_SAMPLES_PER_BLOCK;
|
||||
sh_audio->ds->ss_mul = sh_audio->wf->nBlockAlign;
|
||||
break;
|
||||
case AFM_FOX61ADPCM:
|
||||
sh_audio->audio_out_minsize=FOX61_ADPCM_SAMPLES_PER_BLOCK * 4;
|
||||
sh_audio->ds->ss_div=FOX61_ADPCM_SAMPLES_PER_BLOCK;
|
||||
sh_audio->ds->ss_mul=FOX61_ADPCM_BLOCK_SIZE;
|
||||
case AFM_DK4ADPCM:
|
||||
sh_audio->audio_out_minsize=DK4_ADPCM_SAMPLES_PER_BLOCK * 4;
|
||||
sh_audio->ds->ss_div=DK4_ADPCM_SAMPLES_PER_BLOCK;
|
||||
sh_audio->ds->ss_mul=sh_audio->wf->nBlockAlign;
|
||||
break;
|
||||
case AFM_FOX62ADPCM:
|
||||
sh_audio->audio_out_minsize=FOX62_ADPCM_SAMPLES_PER_BLOCK * 4;
|
||||
sh_audio->ds->ss_div=FOX62_ADPCM_SAMPLES_PER_BLOCK;
|
||||
sh_audio->ds->ss_mul=FOX62_ADPCM_BLOCK_SIZE;
|
||||
case AFM_DK3ADPCM:
|
||||
sh_audio->audio_out_minsize=DK3_ADPCM_SAMPLES_PER_BLOCK * 4;
|
||||
sh_audio->ds->ss_div=DK3_ADPCM_SAMPLES_PER_BLOCK;
|
||||
sh_audio->ds->ss_mul=DK3_ADPCM_BLOCK_SIZE;
|
||||
break;
|
||||
case AFM_ROQAUDIO:
|
||||
// minsize was stored in wf->nBlockAlign by the RoQ demuxer
|
||||
sh_audio->audio_out_minsize=sh_audio->wf->nBlockAlign;
|
||||
sh_audio->ds->ss_div=FOX62_ADPCM_SAMPLES_PER_BLOCK;
|
||||
sh_audio->ds->ss_mul=FOX62_ADPCM_BLOCK_SIZE;
|
||||
sh_audio->ds->ss_div=DK3_ADPCM_SAMPLES_PER_BLOCK;
|
||||
sh_audio->ds->ss_mul=DK3_ADPCM_BLOCK_SIZE;
|
||||
sh_audio->context = roq_decode_audio_init();
|
||||
break;
|
||||
case AFM_MPEG:
|
||||
@ -724,17 +724,17 @@ case AFM_MSADPCM:
|
||||
sh_audio->i_bps = sh_audio->wf->nBlockAlign *
|
||||
(sh_audio->channels*sh_audio->samplerate) / MS_ADPCM_SAMPLES_PER_BLOCK;
|
||||
break;
|
||||
case AFM_FOX61ADPCM:
|
||||
case AFM_DK4ADPCM:
|
||||
sh_audio->channels=sh_audio->wf->nChannels;
|
||||
sh_audio->samplerate=sh_audio->wf->nSamplesPerSec;
|
||||
sh_audio->i_bps=FOX61_ADPCM_BLOCK_SIZE*
|
||||
(sh_audio->channels*sh_audio->samplerate) / FOX61_ADPCM_SAMPLES_PER_BLOCK;
|
||||
sh_audio->i_bps = sh_audio->wf->nBlockAlign *
|
||||
(sh_audio->channels*sh_audio->samplerate) / DK4_ADPCM_SAMPLES_PER_BLOCK;
|
||||
break;
|
||||
case AFM_FOX62ADPCM:
|
||||
case AFM_DK3ADPCM:
|
||||
sh_audio->channels=sh_audio->wf->nChannels;
|
||||
sh_audio->samplerate=sh_audio->wf->nSamplesPerSec;
|
||||
sh_audio->i_bps=FOX62_ADPCM_BLOCK_SIZE*
|
||||
(sh_audio->channels*sh_audio->samplerate) / FOX62_ADPCM_SAMPLES_PER_BLOCK;
|
||||
sh_audio->i_bps=DK3_ADPCM_BLOCK_SIZE*
|
||||
(sh_audio->channels*sh_audio->samplerate) / DK3_ADPCM_SAMPLES_PER_BLOCK;
|
||||
break;
|
||||
case AFM_ROQAUDIO:
|
||||
sh_audio->channels=sh_audio->wf->nChannels;
|
||||
@ -1163,21 +1163,24 @@ int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int minlen,int maxlen){
|
||||
sh_audio->wf->nBlockAlign);
|
||||
break;
|
||||
}
|
||||
case AFM_FOX61ADPCM:
|
||||
{ unsigned char ibuf[FOX61_ADPCM_BLOCK_SIZE]; // bytes / stereo frame
|
||||
if (demux_read_data(sh_audio->ds, ibuf, FOX61_ADPCM_BLOCK_SIZE) !=
|
||||
FOX61_ADPCM_BLOCK_SIZE)
|
||||
case AFM_DK4ADPCM:
|
||||
{ static unsigned char *ibuf = NULL;
|
||||
if (!ibuf)
|
||||
ibuf = (unsigned char *)malloc(sh_audio->wf->nBlockAlign);
|
||||
if (demux_read_data(sh_audio->ds, ibuf, sh_audio->wf->nBlockAlign) !=
|
||||
sh_audio->wf->nBlockAlign)
|
||||
break; // EOF
|
||||
len=2*fox61_adpcm_decode_block((unsigned short*)buf,ibuf);
|
||||
len=2*dk4_adpcm_decode_block((unsigned short*)buf,ibuf,
|
||||
sh_audio->wf->nChannels, sh_audio->wf->nBlockAlign);
|
||||
break;
|
||||
}
|
||||
case AFM_FOX62ADPCM:
|
||||
{ unsigned char ibuf[FOX62_ADPCM_BLOCK_SIZE * 2]; // bytes / stereo frame
|
||||
case AFM_DK3ADPCM:
|
||||
{ unsigned char ibuf[DK3_ADPCM_BLOCK_SIZE * 2]; // bytes / stereo frame
|
||||
if (demux_read_data(sh_audio->ds, ibuf,
|
||||
FOX62_ADPCM_BLOCK_SIZE * sh_audio->wf->nChannels) !=
|
||||
FOX62_ADPCM_BLOCK_SIZE * sh_audio->wf->nChannels)
|
||||
DK3_ADPCM_BLOCK_SIZE * sh_audio->wf->nChannels) !=
|
||||
DK3_ADPCM_BLOCK_SIZE * sh_audio->wf->nChannels)
|
||||
break; // EOF
|
||||
len = 2 * fox62_adpcm_decode_block(
|
||||
len = 2 * dk3_adpcm_decode_block(
|
||||
(unsigned short*)buf,ibuf);
|
||||
break;
|
||||
}
|
||||
|
@ -384,19 +384,19 @@ audiocodec msadpcm
|
||||
format 0x2
|
||||
driver msadpcm
|
||||
|
||||
audiocodec fox61adpcm
|
||||
audiocodec dk4adpcm
|
||||
info "Duck DK4 ADPCM (rogue format number)"
|
||||
status working
|
||||
comment "This format number was used by Duck Corp. but not officially registered with Microsoft"
|
||||
format 0x61
|
||||
driver fox61adpcm
|
||||
driver dk4adpcm
|
||||
|
||||
audiocodec fox62adpcm
|
||||
audiocodec dk3adpcm
|
||||
info "Duck DK3 ADPCM (rogue format number)"
|
||||
status working
|
||||
comment "This format number was used by Duck Corp. but not officially registered with Microsoft"
|
||||
format 0x62
|
||||
driver fox62adpcm
|
||||
driver dk3adpcm
|
||||
|
||||
audiocodec roqaudio
|
||||
info "Id RoQ File Audio Decoder"
|
||||
|
Loading…
Reference in New Issue
Block a user