mapping0.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. /********************************************************************
  2. * *
  3. * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. *
  4. * *
  5. * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
  6. * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
  7. * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
  8. * *
  9. * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 *
  10. * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ *
  11. * *
  12. ********************************************************************
  13. function: channel mapping 0 implementation
  14. ********************************************************************/
  15. #include <stdlib.h>
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include <math.h>
  19. #include "ogg.h"
  20. #include "os.h"
  21. #include "ivorbiscodec.h"
  22. #include "mdct.h"
  23. #include "codec_internal.h"
  24. #include "codebook.h"
  25. #include "misc.h"
  26. void mapping_clear_info(vorbis_info_mapping *info){
  27. if(info){
  28. if(info->chmuxlist)_ogg_free(info->chmuxlist);
  29. if(info->submaplist)_ogg_free(info->submaplist);
  30. if(info->coupling)_ogg_free(info->coupling);
  31. memset(info,0,sizeof(*info));
  32. }
  33. }
  34. static int ilog(unsigned int v){
  35. int ret=0;
  36. if(v)--v;
  37. while(v){
  38. ret++;
  39. v>>=1;
  40. }
  41. return(ret);
  42. }
  43. /* also responsible for range checking */
  44. int mapping_info_unpack(vorbis_info_mapping *info,vorbis_info *vi,
  45. oggpack_buffer *opb){
  46. int i;
  47. codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
  48. memset(info,0,sizeof(*info));
  49. if(oggpack_read(opb,1))
  50. info->submaps=oggpack_read(opb,4)+1;
  51. else
  52. info->submaps=1;
  53. if(oggpack_read(opb,1)){
  54. info->coupling_steps=oggpack_read(opb,8)+1;
  55. info->coupling=
  56. _ogg_malloc(info->coupling_steps*sizeof(*info->coupling));
  57. for(i=0;i<info->coupling_steps;i++){
  58. int testM=info->coupling[i].mag=oggpack_read(opb,ilog(vi->channels));
  59. int testA=info->coupling[i].ang=oggpack_read(opb,ilog(vi->channels));
  60. if(testM<0 ||
  61. testA<0 ||
  62. testM==testA ||
  63. testM>=vi->channels ||
  64. testA>=vi->channels) goto err_out;
  65. }
  66. }
  67. if(oggpack_read(opb,2)>0)goto err_out; /* 2,3:reserved */
  68. if(info->submaps>1){
  69. info->chmuxlist=_ogg_malloc(sizeof(*info->chmuxlist)*vi->channels);
  70. for(i=0;i<vi->channels;i++){
  71. info->chmuxlist[i]=oggpack_read(opb,4);
  72. if(info->chmuxlist[i]>=info->submaps)goto err_out;
  73. }
  74. }
  75. info->submaplist=_ogg_malloc(sizeof(*info->submaplist)*info->submaps);
  76. for(i=0;i<info->submaps;i++){
  77. int temp=oggpack_read(opb,8);
  78. info->submaplist[i].floor=oggpack_read(opb,8);
  79. if(info->submaplist[i].floor>=ci->floors)goto err_out;
  80. info->submaplist[i].residue=oggpack_read(opb,8);
  81. if(info->submaplist[i].residue>=ci->residues)goto err_out;
  82. }
  83. return 0;
  84. err_out:
  85. mapping_clear_info(info);
  86. return -1;
  87. }
  88. int mapping_inverse(vorbis_dsp_state *vd,vorbis_info_mapping *info){
  89. vorbis_info *vi=vd->vi;
  90. codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
  91. int i,j;
  92. long n=ci->blocksizes[vd->W];
  93. ogg_int32_t **pcmbundle=
  94. alloca(sizeof(*pcmbundle)*vi->channels);
  95. int *zerobundle=
  96. alloca(sizeof(*zerobundle)*vi->channels);
  97. int *nonzero=
  98. alloca(sizeof(*nonzero)*vi->channels);
  99. ogg_int32_t **floormemo=
  100. alloca(sizeof(*floormemo)*vi->channels);
  101. /* recover the spectral envelope; store it in the PCM vector for now */
  102. for(i=0;i<vi->channels;i++){
  103. int submap=0;
  104. int floorno;
  105. if(info->submaps>1)
  106. submap=info->chmuxlist[i];
  107. floorno=info->submaplist[submap].floor;
  108. if(ci->floor_type[floorno]){
  109. /* floor 1 */
  110. floormemo[i]=alloca(sizeof(*floormemo[i])*
  111. floor1_memosize(ci->floor_param[floorno]));
  112. floormemo[i]=floor1_inverse1(vd,ci->floor_param[floorno],floormemo[i]);
  113. }else{
  114. /* floor 0 */
  115. floormemo[i]=alloca(sizeof(*floormemo[i])*
  116. floor0_memosize(ci->floor_param[floorno]));
  117. floormemo[i]=floor0_inverse1(vd,ci->floor_param[floorno],floormemo[i]);
  118. }
  119. if(floormemo[i])
  120. nonzero[i]=1;
  121. else
  122. nonzero[i]=0;
  123. memset(vd->work[i],0,sizeof(*vd->work[i])*n/2);
  124. }
  125. /* channel coupling can 'dirty' the nonzero listing */
  126. for(i=0;i<info->coupling_steps;i++){
  127. if(nonzero[info->coupling[i].mag] ||
  128. nonzero[info->coupling[i].ang]){
  129. nonzero[info->coupling[i].mag]=1;
  130. nonzero[info->coupling[i].ang]=1;
  131. }
  132. }
  133. /* recover the residue into our working vectors */
  134. for(i=0;i<info->submaps;i++){
  135. int ch_in_bundle=0;
  136. for(j=0;j<vi->channels;j++){
  137. if(!info->chmuxlist || info->chmuxlist[j]==i){
  138. if(nonzero[j])
  139. zerobundle[ch_in_bundle]=1;
  140. else
  141. zerobundle[ch_in_bundle]=0;
  142. pcmbundle[ch_in_bundle++]=vd->work[j];
  143. }
  144. }
  145. res_inverse(vd,ci->residue_param+info->submaplist[i].residue,
  146. pcmbundle,zerobundle,ch_in_bundle);
  147. }
  148. //for(j=0;j<vi->channels;j++)
  149. //_analysis_output("coupled",seq+j,vb->pcm[j],-8,n/2,0,0);
  150. /* channel coupling */
  151. for(i=info->coupling_steps-1;i>=0;i--){
  152. ogg_int32_t *pcmM=vd->work[info->coupling[i].mag];
  153. ogg_int32_t *pcmA=vd->work[info->coupling[i].ang];
  154. for(j=0;j<n/2;j++){
  155. ogg_int32_t mag=pcmM[j];
  156. ogg_int32_t ang=pcmA[j];
  157. if(mag>0)
  158. if(ang>0){
  159. pcmM[j]=mag;
  160. pcmA[j]=mag-ang;
  161. }else{
  162. pcmA[j]=mag;
  163. pcmM[j]=mag+ang;
  164. }
  165. else
  166. if(ang>0){
  167. pcmM[j]=mag;
  168. pcmA[j]=mag+ang;
  169. }else{
  170. pcmA[j]=mag;
  171. pcmM[j]=mag-ang;
  172. }
  173. }
  174. }
  175. //for(j=0;j<vi->channels;j++)
  176. //_analysis_output("residue",seq+j,vb->pcm[j],-8,n/2,0,0);
  177. /* compute and apply spectral envelope */
  178. for(i=0;i<vi->channels;i++){
  179. ogg_int32_t *pcm=vd->work[i];
  180. int submap=0;
  181. int floorno;
  182. if(info->submaps>1)
  183. submap=info->chmuxlist[i];
  184. floorno=info->submaplist[submap].floor;
  185. if(ci->floor_type[floorno]){
  186. /* floor 1 */
  187. floor1_inverse2(vd,ci->floor_param[floorno],floormemo[i],pcm);
  188. }else{
  189. /* floor 0 */
  190. floor0_inverse2(vd,ci->floor_param[floorno],floormemo[i],pcm);
  191. }
  192. }
  193. //for(j=0;j<vi->channels;j++)
  194. //_analysis_output("mdct",seq+j,vb->pcm[j],-24,n/2,0,1);
  195. /* transform the PCM data; takes PCM vector, vb; modifies PCM vector */
  196. /* only MDCT right now.... */
  197. for(i=0;i<vi->channels;i++)
  198. mdct_backward(n,vd->work[i]);
  199. //for(j=0;j<vi->channels;j++)
  200. //_analysis_output("imdct",seq+j,vb->pcm[j],-24,n,0,0);
  201. /* all done! */
  202. return(0);
  203. }