opusfile_example.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. /********************************************************************
  2. * *
  3. * THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. *
  4. * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
  5. * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
  6. * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
  7. * *
  8. * THE libopusfile SOURCE CODE IS (C) COPYRIGHT 1994-2012 *
  9. * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
  10. * *
  11. ********************************************************************/
  12. /*For fileno()*/
  13. #if !defined(_POSIX_SOURCE)
  14. # define _POSIX_SOURCE 1
  15. #endif
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <errno.h>
  19. #include <string.h>
  20. #if defined(_WIN32)
  21. /*We need the following two to set stdin/stdout to binary.*/
  22. # include <io.h>
  23. # include <fcntl.h>
  24. #endif
  25. #include <opusfile.h>
  26. #if defined(OP_FIXED_POINT)
  27. typedef opus_int16 op_sample;
  28. # define op_read_native_stereo op_read_stereo
  29. #else
  30. typedef float op_sample;
  31. # define op_read_native_stereo op_read_float_stereo
  32. #endif
  33. static void print_duration(FILE *_fp,ogg_int64_t _nsamples,int _frac){
  34. ogg_int64_t seconds;
  35. ogg_int64_t minutes;
  36. ogg_int64_t hours;
  37. ogg_int64_t days;
  38. ogg_int64_t weeks;
  39. _nsamples+=_frac?24:24000;
  40. seconds=_nsamples/48000;
  41. _nsamples-=seconds*48000;
  42. minutes=seconds/60;
  43. seconds-=minutes*60;
  44. hours=minutes/60;
  45. minutes-=hours*60;
  46. days=hours/24;
  47. hours-=days*24;
  48. weeks=days/7;
  49. days-=weeks*7;
  50. if(weeks)fprintf(_fp,"%liw",(long)weeks);
  51. if(weeks||days)fprintf(_fp,"%id",(int)days);
  52. if(weeks||days||hours){
  53. if(weeks||days)fprintf(_fp,"%02ih",(int)hours);
  54. else fprintf(_fp,"%ih",(int)hours);
  55. }
  56. if(weeks||days||hours||minutes){
  57. if(weeks||days||hours)fprintf(_fp,"%02im",(int)minutes);
  58. else fprintf(_fp,"%im",(int)minutes);
  59. fprintf(_fp,"%02i",(int)seconds);
  60. }
  61. else fprintf(_fp,"%i",(int)seconds);
  62. if(_frac)fprintf(_fp,".%03i",(int)(_nsamples/48));
  63. fprintf(_fp,"s");
  64. }
  65. static void print_size(FILE *_fp,opus_int64 _nbytes,int _metric,
  66. const char *_spacer){
  67. static const char SUFFIXES[7]={' ','k','M','G','T','P','E'};
  68. opus_int64 val;
  69. opus_int64 den;
  70. opus_int64 round;
  71. int base;
  72. int shift;
  73. base=_metric?1000:1024;
  74. round=0;
  75. den=1;
  76. for(shift=0;shift<6;shift++){
  77. if(_nbytes<den*base-round)break;
  78. den*=base;
  79. round=den>>1;
  80. }
  81. val=(_nbytes+round)/den;
  82. if(den>1&&val<10){
  83. if(den>=1000000000)val=(_nbytes+(round/100))/(den/100);
  84. else val=(_nbytes*100+round)/den;
  85. fprintf(_fp,"%li.%02i%s%c",(long)(val/100),(int)(val%100),
  86. _spacer,SUFFIXES[shift]);
  87. }
  88. else if(den>1&&val<100){
  89. if(den>=1000000000)val=(_nbytes+(round/10))/(den/10);
  90. else val=(_nbytes*10+round)/den;
  91. fprintf(_fp,"%li.%i%s%c",(long)(val/10),(int)(val%10),
  92. _spacer,SUFFIXES[shift]);
  93. }
  94. else fprintf(_fp,"%li%s%c",(long)val,_spacer,SUFFIXES[shift]);
  95. }
  96. int main(int _argc,const char **_argv){
  97. OggOpusFile *of;
  98. ogg_int64_t pcm_offset;
  99. ogg_int64_t pcm_print_offset;
  100. ogg_int64_t nsamples;
  101. opus_int32 bitrate;
  102. int ret;
  103. int prev_li;
  104. int is_ssl;
  105. #if defined(_WIN32)
  106. # undef fileno
  107. # define fileno _fileno
  108. /*We need to set stdin/stdout to binary mode. Damn windows.*/
  109. /*Beware the evil ifdef. We avoid these where we can, but this one we
  110. cannot.
  111. Don't add any more.
  112. You'll probably go to hell if you do.*/
  113. _setmode(fileno(stdin),_O_BINARY);
  114. _setmode(fileno(stdout),_O_BINARY);
  115. #endif
  116. if(_argc!=2){
  117. fprintf(stderr,"Usage: %s <file.opus>\n",_argv[0]);
  118. return EXIT_FAILURE;
  119. }
  120. is_ssl=0;
  121. if(strcmp(_argv[1],"-")==0){
  122. OpusFileCallbacks cb={NULL,NULL,NULL,NULL};
  123. of=op_open_callbacks(op_fdopen(&cb,fileno(stdin),"rb"),&cb,NULL,0,&ret);
  124. }
  125. else{
  126. /*Try to treat the argument as a URL.*/
  127. of=op_open_url(_argv[1],&ret,NULL);
  128. #if 0
  129. if(of==NULL){
  130. OpusFileCallbacks cb={NULL,NULL,NULL,NULL};
  131. void *fp;
  132. /*For debugging: force a file to not be seekable.*/
  133. fp=op_fopen(&cb,_argv[1],"rb");
  134. cb.seek=NULL;
  135. cb.tell=NULL;
  136. of=op_open_callbacks(fp,&cb,NULL,0,NULL);
  137. }
  138. #else
  139. if(of==NULL)of=op_open_file(_argv[1],&ret);
  140. /*This is not a very good check, but at least it won't give false
  141. positives.*/
  142. else is_ssl=strncmp(_argv[1],"https:",6)==0;
  143. #endif
  144. }
  145. if(of==NULL){
  146. fprintf(stderr,"Failed to open file '%s': %i\n",_argv[1],ret);
  147. return EXIT_FAILURE;
  148. }
  149. if(op_seekable(of)){
  150. ogg_int64_t duration;
  151. opus_int64 size;
  152. fprintf(stderr,"Total number of links: %i\n",op_link_count(of));
  153. duration=op_pcm_total(of,-1);
  154. fprintf(stderr,"Total duration: ");
  155. print_duration(stderr,duration,3);
  156. fprintf(stderr," (%li samples @ 48 kHz)\n",(long)duration);
  157. size=op_raw_total(of,-1);
  158. fprintf(stderr,"Total size: ");
  159. print_size(stderr,size,0,"");
  160. fprintf(stderr,"\n");
  161. }
  162. prev_li=-1;
  163. nsamples=0;
  164. pcm_offset=op_pcm_tell(of);
  165. if(pcm_offset!=0){
  166. fprintf(stderr,"Non-zero starting PCM offset: %li\n",(long)pcm_offset);
  167. }
  168. pcm_print_offset=pcm_offset-48000;
  169. bitrate=0;
  170. for(;;){
  171. ogg_int64_t next_pcm_offset;
  172. op_sample pcm[120*48*2];
  173. int li;
  174. ret=op_read_native_stereo(of,pcm,sizeof(pcm)/sizeof(*pcm));
  175. if(ret<0){
  176. fprintf(stderr,"\nError decoding '%s': %i\n",_argv[1],ret);
  177. if(is_ssl)fprintf(stderr,"Possible truncation attack?\n");
  178. ret=EXIT_FAILURE;
  179. break;
  180. }
  181. li=op_current_link(of);
  182. if(li!=prev_li){
  183. const OpusHead *head;
  184. const OpusTags *tags;
  185. int ci;
  186. /*We found a new link.
  187. Print out some information.*/
  188. fprintf(stderr,"Decoding link %i: \n",li);
  189. head=op_head(of,li);
  190. fprintf(stderr," Channels: %i\n",head->channel_count);
  191. if(op_seekable(of)){
  192. ogg_int64_t duration;
  193. opus_int64 size;
  194. duration=op_pcm_total(of,li);
  195. fprintf(stderr," Duration: ");
  196. print_duration(stderr,duration,3);
  197. fprintf(stderr," (%li samples @ 48 kHz)\n",(long)duration);
  198. size=op_raw_total(of,li);
  199. fprintf(stderr," Size: ");
  200. print_size(stderr,size,0,"");
  201. fprintf(stderr,"\n");
  202. }
  203. if(head->input_sample_rate){
  204. fprintf(stderr," Original sampling rate: %lu Hz\n",
  205. (unsigned long)head->input_sample_rate);
  206. }
  207. tags=op_tags(of,li);
  208. fprintf(stderr," Encoded by: %s\n",tags->vendor);
  209. for(ci=0;ci<tags->comments;ci++){
  210. fprintf(stderr," %s\n",tags->user_comments[ci]);
  211. }
  212. fprintf(stderr,"\n");
  213. if(!op_seekable(of)){
  214. pcm_offset=op_pcm_tell(of)-ret;
  215. if(pcm_offset!=0){
  216. fprintf(stderr,"Non-zero starting PCM offset in link %i: %li\n",
  217. li,(long)pcm_offset);
  218. }
  219. }
  220. }
  221. if(li!=prev_li||pcm_offset>=pcm_print_offset+48000){
  222. opus_int32 next_bitrate;
  223. opus_int64 raw_offset;
  224. next_bitrate=op_bitrate_instant(of);
  225. if(next_bitrate>=0)bitrate=next_bitrate;
  226. raw_offset=op_raw_tell(of);
  227. fprintf(stderr,"\r ");
  228. print_size(stderr,raw_offset,0,"");
  229. fprintf(stderr," ");
  230. print_duration(stderr,pcm_offset,0);
  231. fprintf(stderr," (");
  232. print_size(stderr,bitrate,1," ");
  233. fprintf(stderr,"bps) \r");
  234. pcm_print_offset=pcm_offset;
  235. }
  236. next_pcm_offset=op_pcm_tell(of);
  237. if(pcm_offset+ret!=next_pcm_offset){
  238. fprintf(stderr,"\nPCM offset gap! %li+%i!=%li\n",
  239. (long)pcm_offset,ret,(long)next_pcm_offset);
  240. }
  241. pcm_offset=next_pcm_offset;
  242. if(ret<=0){
  243. ret=EXIT_SUCCESS;
  244. break;
  245. }
  246. if(!fwrite(pcm,sizeof(*pcm)*2,ret,stdout)){
  247. fprintf(stderr,"\nError writing decoded audio data: %s\n",
  248. strerror(errno));
  249. ret=EXIT_FAILURE;
  250. break;
  251. }
  252. nsamples+=ret;
  253. prev_li=li;
  254. }
  255. op_free(of);
  256. if(ret==EXIT_SUCCESS){
  257. fprintf(stderr,"\nDone: played ");
  258. print_duration(stderr,nsamples,3);
  259. fprintf(stderr," (%li samples @ 48 kHz).\n",(long)nsamples);
  260. }
  261. return ret;
  262. }