oggencoder.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. //oggencoder.c
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <errno.h>
  5. #include <string.h>
  6. #include <time.h>
  7. #include <math.h>
  8. #include <vorbis/vorbisenc.h>
  9. //#include <vorbisenc.h>
  10. #define READ 1024
  11. typedef struct oggwriter oggwriter;
  12. struct oggwriter{
  13. ogg_stream_state os; //take physical pages, weld into a logical stream of packets
  14. ogg_page og; //one Ogg bitstream page. Vorbis packets are inside
  15. ogg_packet op; //one raw packet of data for decode
  16. vorbis_info vi; //struct that stores all the static vorbis bitstream settings
  17. vorbis_comment vc; //struct that stores all the user comments
  18. vorbis_dsp_state vd; //central working state for the packet->PCM decoder
  19. vorbis_block vb; //local working space for packet->PCM decode
  20. };
  21. int Encode_Ogg(void *stream,void(*writefunc)(void *bytes,int count,void *stream),int freq,int channels,float *samples,int length,float compression){
  22. oggwriter *ogg;
  23. int eos;
  24. int result;
  25. ogg=(oggwriter*)malloc(sizeof(oggwriter));
  26. vorbis_info_init(&ogg->vi);
  27. result=vorbis_encode_init_vbr(&ogg->vi,channels,freq,compression);
  28. if(result) return -1; //error format not supported...
  29. // add a comment
  30. vorbis_comment_init(&ogg->vc);
  31. vorbis_comment_add_tag(&ogg->vc,"ENCODER","encoder_example.c");
  32. // set up the analysis state and auxiliary encoding storage
  33. vorbis_analysis_init(&ogg->vd,&ogg->vi);
  34. vorbis_block_init(&ogg->vd,&ogg->vb);
  35. srand(time(NULL));
  36. ogg_stream_init(&ogg->os,rand());
  37. ogg_packet header;
  38. ogg_packet header_comm;
  39. ogg_packet header_code;
  40. vorbis_analysis_headerout(&ogg->vd,&ogg->vc,&header,&header_comm,&header_code);
  41. ogg_stream_packetin(&ogg->os,&header); //automatically placed in its own page
  42. ogg_stream_packetin(&ogg->os,&header_comm);
  43. ogg_stream_packetin(&ogg->os,&header_code);
  44. //This ensures the actual audio data will start on a new page, as per spec
  45. while(1){
  46. result=ogg_stream_flush(&ogg->os,&ogg->og);
  47. if(result==0)break;
  48. writefunc(ogg->og.header,ogg->og.header_len,stream);
  49. writefunc(ogg->og.body,ogg->og.body_len,stream);
  50. }
  51. int i,c,n;
  52. eos=0;
  53. while(!eos){
  54. if (length>0){
  55. float **buffer=vorbis_analysis_buffer(&ogg->vd,READ);
  56. n=length;if (n>READ) n=READ;
  57. //uninterleave samples
  58. for (i=0;i<n;i++){
  59. for (c=0;c<channels;c++){
  60. buffer[c][i]=*samples++;
  61. }
  62. }
  63. length=length-n;
  64. //tell the library how much we actually submitted
  65. vorbis_analysis_wrote(&ogg->vd,i);
  66. }else{
  67. vorbis_analysis_wrote(&ogg->vd,0);
  68. }
  69. while(vorbis_analysis_blockout(&ogg->vd,&ogg->vb)==1){
  70. //analysis, assume we want to use bitrate management
  71. vorbis_analysis(&ogg->vb,NULL);
  72. vorbis_bitrate_addblock(&ogg->vb);
  73. while(vorbis_bitrate_flushpacket(&ogg->vd,&ogg->op)){
  74. //weld the packet into the bitstream
  75. ogg_stream_packetin(&ogg->os,&ogg->op);
  76. //write out pages (if any)
  77. while(!eos){
  78. result=ogg_stream_pageout(&ogg->os,&ogg->og);
  79. if(result==0)break;
  80. writefunc(ogg->og.header,ogg->og.header_len,stream);
  81. writefunc(ogg->og.body,ogg->og.body_len,stream);
  82. if (ogg_page_eos(&ogg->og)) eos=1;
  83. }
  84. }
  85. }
  86. }
  87. //clean up and exit. vorbis_info_clear() must be called last
  88. ogg_stream_clear(&ogg->os);
  89. vorbis_block_clear(&ogg->vb);
  90. vorbis_dsp_clear(&ogg->vd);
  91. vorbis_comment_clear(&ogg->vc);
  92. vorbis_info_clear(&ogg->vi);
  93. free(ogg);
  94. return 0;
  95. }