/* simplistic, wasteful way of doing this (unique lookup for each mode/submapping); there should be a central repository for * identical lookups. That will require minor work, so I'm putting it off as low priority. * * Why a lookup for each backend in a given mode? Because the blocksize is set by the mode, and low backend lookups may require * parameters from other areas of the mode/mapping */ static void mapping0_free_info(ref vorbis_info_mapping i) { vorbis_info_mapping0 info = i as vorbis_info_mapping0; if (info != null) { info = null; } }
static void mapping0_pack(ref vorbis_info vi, vorbis_info_mapping vm, ref Ogg.oggpack_buffer opb) { int i; vorbis_info_mapping0 info = vm as vorbis_info_mapping0; /* another 'we meant to do it this way' hack... up to beta 4, we packed 4 binary zeros here to signify one submapping in use. We * now redefine that to mean four bitflags that indicate use of deeper features; bit0:submappings, bit1:coupling, * bit2,3: reserved. This is backward compatable with all actual uses of the beta code. */ if (info.submaps > 1) { Ogg.oggpack_write(ref opb, 1, 1); Ogg.oggpack_write(ref opb, (uint)(info.submaps - 1), 4); } else { Ogg.oggpack_write(ref opb, 0, 1); } if (info.coupling_steps > 0) { Ogg.oggpack_write(ref opb, 1, 1); Ogg.oggpack_write(ref opb, (uint)(info.coupling_steps - 1), 8); for (i = 0; i < info.coupling_steps; i++) { Ogg.oggpack_write(ref opb, (uint)info.coupling_mag[i], ilog((uint)vi.channels)); Ogg.oggpack_write(ref opb, (uint)info.coupling_ang[i], ilog((uint)vi.channels)); } } else { Ogg.oggpack_write(ref opb, 0, 1); } Ogg.oggpack_write(ref opb, 0, 2); /* 2,3:reserved */ /* we don't write the channel submappings if we only have one... */ if (info.submaps > 1) { for (i = 0; i < vi.channels; i++) { Ogg.oggpack_write(ref opb, (uint)info.chmuxlist[i], 4); } } for (i = 0; i < info.submaps; i++) { Ogg.oggpack_write(ref opb, 0, 8); /* time submap unused */ Ogg.oggpack_write(ref opb, (uint)info.floorsubmap[i], 8); Ogg.oggpack_write(ref opb, (uint)info.residuesubmap[i], 8); } }
static int mapping0_inverse(ref vorbis_block vb, vorbis_info_mapping l) { vorbis_dsp_state vd = vb.vd; vorbis_info vi = vd.vi; codec_setup_info ci = vi.codec_setup as codec_setup_info; private_state b = vd.backend_state as private_state; vorbis_info_mapping0 info = l as vorbis_info_mapping0; int i, j; int n = vb.pcmend = ci.blocksizes[vb.W]; float **pcmbundle = stackalloc float *[vi.channels]; int * zerobundle = stackalloc int[vi.channels]; int * nonzero = stackalloc int[vi.channels]; void **floormemo = stackalloc void *[vi.channels]; /* recover the spectral envelope; store it in the PCM vector for now */ for (i = 0; i < vi.channels; i++) { int submap = info.chmuxlist[i]; floormemo[i] = _floor_P[ci.floor_type[info.floorsubmap[submap]]].inverse1(ref vb, b.flr[info.floorsubmap[submap]]); if (floormemo[i] != null) { nonzero[i] = 1; } else { nonzero[i] = 0; } ZeroMemory(vb.pcm[i], sizeof(float) * n / 2); } /* channel coupling can 'dirty' the nonzero listing */ for (i = 0; i < info.coupling_steps; i++) { if (nonzero[info.coupling_mag[i]] != 0 || nonzero[info.coupling_ang[i]] != 0) { nonzero[info.coupling_mag[i]] = 1; nonzero[info.coupling_ang[i]] = 1; } } /* recover the residue into our working vectors */ for (i = 0; i < info.submaps; i++) { int ch_in_bundle = 0; for (j = 0; j < vi.channels; j++) { if (info.chmuxlist[j] == i) { if (nonzero[j] != 0) { zerobundle[ch_in_bundle] = 1; } else { zerobundle[ch_in_bundle] = 0; } pcmbundle[ch_in_bundle++] = vb.pcm[j]; } } _residue_P[ci.residue_type[info.residuesubmap[i]]].inverse(ref vb, b.residue[info.residuesubmap[i]], pcmbundle, zerobundle, ch_in_bundle); } /* channel coupling */ for (i = info.coupling_steps - 1; i >= 0; i--) { float *pcmM = vb.pcm[info.coupling_mag[i]]; float *pcmA = vb.pcm[info.coupling_ang[i]]; for (j = 0; j < n / 2; j++) { float mag = pcmM[j]; float ang = pcmA[j]; if (mag > 0) { if (ang > 0) { pcmM[j] = mag; pcmA[j] = mag - ang; } else { pcmA[j] = mag; pcmM[j] = mag + ang; } } else { if (ang > 0) { pcmM[j] = mag; pcmA[j] = mag + ang; } else { pcmA[j] = mag; pcmM[j] = mag - ang; } } } } /* compute and apply spectral envelope */ for (i = 0; i < vi.channels; i++) { float *pcm = vb.pcm[i]; int submap = info.chmuxlist[i]; _floor_P[ci.floor_type[info.floorsubmap[submap]]].inverse2(ref vb, b.flr[info.floorsubmap[submap]], floormemo[i], pcm); } /* transform the PCM data; takes PCM vector, vb; modifies PCM vector */ /* only MDCT right now.... */ for (i = 0; i < vi.channels; i++) { float *pcm = vb.pcm[i]; mdct_backward(b.transform[vb.W][0] as mdct_lookup, pcm, pcm); } /* all done! */ return(0); }