fix vorbis decoding issues when multiple instances are run on different threads

This commit is contained in:
UnknownShadow200 2018-08-06 02:32:32 +10:00
parent 1e6bcd5306
commit a95d0ba3b1
8 changed files with 45 additions and 56 deletions

View File

@ -69,7 +69,6 @@ namespace ClassicalSharp.Audio {
} }
} }
IAudioOutput firstSoundOut;
void PlayCurrentSound(IAudioOutput[] outputs, float volume) { void PlayCurrentSound(IAudioOutput[] outputs, float volume) {
for (int i = 0; i < monoOutputs.Length; i++) { for (int i = 0; i < monoOutputs.Length; i++) {
IAudioOutput output = outputs[i]; IAudioOutput output = outputs[i];
@ -116,10 +115,6 @@ namespace ClassicalSharp.Audio {
void DisposeSound() { void DisposeSound() {
DisposeOutputs(ref monoOutputs); DisposeOutputs(ref monoOutputs);
DisposeOutputs(ref stereoOutputs); DisposeOutputs(ref stereoOutputs);
if (firstSoundOut != null) {
firstSoundOut.Dispose();
firstSoundOut = null;
}
} }
void DisposeOutputs(ref IAudioOutput[] outputs) { void DisposeOutputs(ref IAudioOutput[] outputs) {

View File

@ -83,8 +83,8 @@ namespace csvorbis
} }
// unpack_header enforces range checking // unpack_header enforces range checking
int type = vi.map_type[vi.mode_param[mode].mapping]; FuncMapping mapping = vi.map_funcs[vi.mode_param[mode].mapping];
return(FuncMapping.mapping_P[type].inverse(this, vd.mode[mode])); return mapping.inverse(this, vd.mode[mode]);
} }
} }
} }

View File

@ -237,7 +237,7 @@ namespace csvorbis
// given a list of word lengths, generate a list of codewords. Works // given a list of word lengths, generate a list of codewords. Works
// for length ordered or unordered, always assigns the lowest valued // for length ordered or unordered, always assigns the lowest valued
// codewords first. Extended to handle unused entries (length 0) // codewords first. Extended to handle unused entries (length 0)
internal static int[] make_words(int[] l, int n) internal int[] make_words(int[] l, int n)
{ {
int[] marker = new int[33]; int[] marker = new int[33];
int[] r = new int[n]; int[] r = new int[n];

View File

@ -31,7 +31,7 @@ namespace csvorbis
{ {
public class DspState public class DspState
{ {
static float M_PI = 3.1415926539f; const float M_PI = 3.1415926539f;
internal Info vi; internal Info vi;
internal int modebits; internal int modebits;
@ -78,7 +78,7 @@ namespace csvorbis
wnd[1][1][1] = new float[2]; wnd[1][1][1] = new float[2];
} }
internal static float[] window(int wnd, int left, int right) internal float[] window(int wnd, int left, int right)
{ {
float[] ret = new float[wnd]; float[] ret = new float[wnd];
// The 'vorbis window' (window 0) is sin(sin(x)*sin(x)*2pi) // The 'vorbis window' (window 0) is sin(sin(x)*sin(x)*2pi)
@ -158,10 +158,9 @@ namespace csvorbis
for(int i = 0;i<vi.modes;i++) { for(int i = 0;i<vi.modes;i++) {
int mapnum = vi.mode_param[i].mapping; int mapnum = vi.mode_param[i].mapping;
int maptype = vi.map_type[mapnum]; FuncMapping mapping = vi.map_funcs[mapnum];
mode[i] = FuncMapping.mapping_P[maptype].look(this,vi.mode_param[i], mode[i] = mapping.look(this,vi.mode_param[i], vi.map_param[mapnum]);
vi.map_param[mapnum]);
} }
} }

View File

@ -30,8 +30,6 @@ namespace csvorbis
{ {
abstract class FuncFloor abstract class FuncFloor
{ {
public static FuncFloor[] floor_P = {null,new Floor1()};
public abstract Object unpack(Info vi, csBuffer opb); public abstract Object unpack(Info vi, csBuffer opb);
public abstract Object look(DspState vd, InfoMode mi, Object i); public abstract Object look(DspState vd, InfoMode mi, Object i);
public abstract Object inverse1(Block vb, Object i, Object memo); public abstract Object inverse1(Block vb, Object i, Object memo);
@ -40,7 +38,7 @@ namespace csvorbis
class Floor1 : FuncFloor class Floor1 : FuncFloor
{ {
static int VIF_POSIT = 63; const int VIF_POSIT = 63;
public override Object unpack(Info vi , csBuffer opb) public override Object unpack(Info vi , csBuffer opb)
{ {
@ -352,7 +350,7 @@ namespace csvorbis
return(null); return(null);
} }
private static int render_point(int x0,int x1,int y0,int y1,int x) private int render_point(int x0,int x1,int y0,int y1,int x)
{ {
y0 &= 0x7fff; /* mask off flag */ y0 &= 0x7fff; /* mask off flag */
y1 &= 0x7fff; y1 &= 0x7fff;
@ -467,7 +465,7 @@ namespace csvorbis
0.82788260F, 0.88168307F, 0.9389798F, 1.0F 0.82788260F, 0.88168307F, 0.9389798F, 1.0F
}; };
private static void render_line(int x0, int x1,int y0,int y1,float[] d) private void render_line(int x0, int x1,int y0,int y1,float[] d)
{ {
int dy = y1-y0; int dy = y1-y0;
int adx = x1-x0; int adx = x1-x0;
@ -535,7 +533,7 @@ namespace csvorbis
class LookFloor1 class LookFloor1
{ {
static int VIF_POSIT = 63; const int VIF_POSIT = 63;
internal int[] sorted_index = new int[VIF_POSIT+2]; internal int[] sorted_index = new int[VIF_POSIT+2];
internal int[] forward_index = new int[VIF_POSIT+2]; internal int[] forward_index = new int[VIF_POSIT+2];

View File

@ -30,8 +30,6 @@ namespace csvorbis
{ {
abstract class FuncMapping abstract class FuncMapping
{ {
public static FuncMapping[] mapping_P = {new Mapping0()};
public abstract Object unpack(Info info , csBuffer buffer); public abstract Object unpack(Info info , csBuffer buffer);
public abstract Object look(DspState vd, InfoMode vm, Object m); public abstract Object look(DspState vd, InfoMode vm, Object m);
public abstract int inverse(Block vd, Object lm); public abstract int inverse(Block vd, Object lm);
@ -58,11 +56,11 @@ namespace csvorbis
int floornum = info.floorsubmap[i]; int floornum = info.floorsubmap[i];
int resnum = info.residuesubmap[i]; int resnum = info.residuesubmap[i];
looks.floor_func[i] = FuncFloor.floor_P[vi.floor_type[floornum]]; looks.floor_func[i] = vi.floor_funcs[floornum];
looks.floor_look[i] = looks.floor_func[i]. looks.floor_look[i] = looks.floor_func[i].
look(vd,vm,vi.floor_param[floornum]); look(vd,vm,vi.floor_param[floornum]);
looks.residue_func[i] = FuncResidue.residue_P[vi.residue_type[resnum]]; looks.residue_func[i] = vi.residue_funcs[resnum];
looks.residue_look[i] = looks.residue_func[i]. looks.residue_look[i] = looks.residue_func[i].
look(vd,vm,vi.residue_param[resnum]); look(vd,vm,vi.residue_param[resnum]);
} }

View File

@ -30,8 +30,11 @@ namespace csvorbis
{ {
abstract class FuncResidue abstract class FuncResidue
{ {
public static FuncResidue[] residue_P = {new Residue0(), new Residue1(), new Residue2()}; public static FuncResidue make(int type) {
if (type == 0) return new Residue0();
if (type == 1) return new Residue1();
return new Residue2();
}
public abstract Object unpack(Info vi, csBuffer opb); public abstract Object unpack(Info vi, csBuffer opb);
public abstract Object look(DspState vd, InfoMode vm, Object vr); public abstract Object look(DspState vd, InfoMode vm, Object vr);
@ -119,9 +122,9 @@ namespace csvorbis
return(look); return(look);
} }
static int[][][] partword = new int[2][][]; int[][][] partword = new int[2][][];
internal static int _01inverse(Block vb, Object vl, float[][] fin, int ch, int decodepart) internal int _01inverse(Block vb, Object vl, float[][] fin, int ch, int decodepart)
{ {
int i,j,k,l,s; int i,j,k,l,s;
LookResidue0 look = (LookResidue0 )vl; LookResidue0 look = (LookResidue0 )vl;
@ -190,7 +193,7 @@ namespace csvorbis
return(0); return(0);
} }
internal static int _2inverse(Block vb, Object vl, float[][] fin, int ch) internal int _2inverse(Block vb, Object vl, float[][] fin, int ch)
{ {
int i,k,l,s; int i,k,l,s;
LookResidue0 look = (LookResidue0 )vl; LookResidue0 look = (LookResidue0 )vl;

View File

@ -38,7 +38,7 @@ namespace csvorbis
public class Info public class Info
{ {
private static int OV_ENOTAUDIO = -135; private const int OV_ENOTAUDIO = -135;
public int version, channels, rate; public int version, channels, rate;
@ -55,13 +55,13 @@ namespace csvorbis
internal InfoMode[] mode_param = null; internal InfoMode[] mode_param = null;
internal int[] map_type = null; internal FuncMapping[] map_funcs = null;
internal Object[] map_param = null; internal Object[] map_param = null;
internal int[] floor_type = null; internal Floor1[] floor_funcs = null;
internal Object[] floor_param = null; internal Object[] floor_param = null;
internal int[] residue_type = null; internal FuncResidue[] residue_funcs = null;
internal Object[] residue_param = null; internal Object[] residue_param = null;
internal StaticCodeBook[] book_param = null; internal StaticCodeBook[] book_param = null;
@ -96,7 +96,7 @@ namespace csvorbis
void unpack_books(csBuffer opb) { void unpack_books(csBuffer opb) {
books = opb.read(8) + 1; books = opb.read(8) + 1;
CheckEntries(ref book_param, books); book_param = new StaticCodeBook[books];
for(int i = 0;i < books;i++) { for(int i = 0;i < books;i++) {
book_param[i] = new StaticCodeBook(); book_param[i] = new StaticCodeBook();
book_param[i].unpack(opb); book_param[i].unpack(opb);
@ -107,28 +107,37 @@ namespace csvorbis
opb.read(16); opb.read(16);
floors = opb.read(6) + 1; floors = opb.read(6) + 1;
CheckEntries(ref floor_param, ref floor_type, floors); floor_funcs = new Floor1[floors];
floor_param = new object[floors];
for(int i = 0;i<floors;i++) { for(int i = 0;i<floors;i++) {
floor_type[i] = opb.read(16); int type = opb.read(16);
floor_param[i] = FuncFloor.floor_P[floor_type[i]].unpack(this,opb); if (type != 1) throw new csorbisException("floor type must be 1");
floor_funcs[i] = new Floor1();
floor_param[i] = floor_funcs[i].unpack(this,opb);
} }
residues = opb.read(6) + 1; residues = opb.read(6) + 1;
CheckEntries(ref residue_param, ref residue_type, residues); residue_funcs = new FuncResidue[residues];
residue_param = new object[residues];
for(int i = 0;i<residues;i++) { for(int i = 0;i<residues;i++) {
residue_type[i] = opb.read(16); int type = opb.read(16);
residue_param[i] = FuncResidue.residue_P[residue_type[i]].unpack(this,opb); if (type > 2) throw new csorbisException("residue type must be <= 2");
residue_funcs[i] = FuncResidue.make(type);
residue_param[i] = residue_funcs[i].unpack(this,opb);
} }
maps = opb.read(6) + 1; maps = opb.read(6) + 1;
CheckEntries(ref map_param, ref map_type, maps); map_funcs = new FuncMapping[maps];
map_param = new object[maps];
for(int i = 0;i<maps;i++) { for(int i = 0;i<maps;i++) {
map_type[i] = opb.read(16); int type = opb.read(16);
map_param[i] = FuncMapping.mapping_P[map_type[i]].unpack(this,opb); if (type != 0) throw new csorbisException("mapping type must be 0");
map_funcs[i] = new Mapping0();
map_param[i] = map_funcs[i].unpack(this,opb);
} }
modes = opb.read(6) + 1; modes = opb.read(6) + 1;
CheckEntries(ref mode_param, modes); mode_param = new InfoMode[modes];
for(int i = 0;i<modes;i++) { for(int i = 0;i<modes;i++) {
mode_param[i] = new InfoMode(); mode_param[i] = new InfoMode();
mode_param[i].blockflag = opb.read(1); mode_param[i].blockflag = opb.read(1);
@ -138,19 +147,6 @@ namespace csvorbis
} }
opb.read(1); opb.read(1);
} }
void CheckEntries<T>(ref T[] array, int count) {
if(array == null || array.Length != count) {
array = new T[count];
}
}
void CheckEntries<T>(ref T[] array, ref int[] types, int count) {
if(array == null || array.Length != count) {
array = new T[count];
types = new int[count];
}
}
public void synthesis_headerin(Comment vc, Packet op) { public void synthesis_headerin(Comment vc, Packet op) {
if(op == null) return; if(op == null) return;