ogg.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. #include "ogg.h"
  2. void OGGFreeFunction(IMaxModMusic* music){
  3. delete static_cast<OggPlayer*>(music);
  4. }
  5. // -----------------------------------------------------------------------------------
  6. size_t readfunc( void* buf,size_t size,size_t nmemb,void* src ){
  7. IMaxModStream* stream = (IMaxModStream*)src;
  8. long int bytes = stream->Read(buf,size*nmemb);
  9. return bytes/size;
  10. }
  11. int seekfunc( void* src, ogg_int64_t off, int whence ){
  12. // cout << "seekfunc " << whence << endl;
  13. IMaxModStream* stream=(IMaxModStream*)src;
  14. int res=-1;
  15. switch(whence) {
  16. // case 0: res=stream->SeekFrom(off,SEEK_SET); cout << "seekfunc SET res=" << res << " offset=" << off << endl; break;
  17. // case 1: res=stream->SeekFrom(off,SEEK_CUR); cout << "seekfunc CUR res=" << res << " offset=" << off << endl; break;
  18. // case 2: res=stream->SeekFrom(off,SEEK_END); cout << "seekfunc END res=" << res << " offset=" << off << endl; break;
  19. case 0: res=stream->SeekFrom(off,SEEK_SET); break;
  20. case 1: res=stream->SeekFrom(off,SEEK_CUR); break;
  21. case 2: res=stream->SeekFrom(off,SEEK_END); break;
  22. }
  23. if (res>=0) return 0;
  24. return -1;
  25. // return res;
  26. }
  27. int closefunc( void* src ){}
  28. long int tellfunc( void* src ){
  29. IMaxModStream* stream=(IMaxModStream*)src;
  30. return stream->Position();
  31. }
  32. // -----------------------------------------------------------------------------------
  33. OggPlayer::OggPlayer(){
  34. Stream = NULL;
  35. FreeFunction = OGGFreeFunction;
  36. }
  37. OggPlayer::~OggPlayer(){
  38. mmPrint("~OggPlayer");
  39. Stop();
  40. if (Stream!=NULL) {
  41. Stream->Close();
  42. delete Stream;
  43. }
  44. }
  45. // -----------------------------------------------------------------------------------
  46. int OggPlayer::FillBuffer(void* buffer,int Length) {
  47. if (Length==0 or STATUS==0) {return 0;}
  48. short* buf = (short*)buffer;
  49. int res,bs,got=0;
  50. while (Length>0){
  51. res=ov_read(&vf,(char*)buf,Length,endian,bits/8,sign,&bs);
  52. if(bs) return 0;
  53. if (res<=0) {
  54. POS=0;
  55. if (LOOP==0) {STATUS=0;return got;}
  56. } else {
  57. got+=res;
  58. buf+=(res/(bits/8));
  59. Length-=res;
  60. POS+=res;
  61. }
  62. if (Stream->Eof()) {
  63. Stream->Seek(0);
  64. }
  65. }
  66. return got;
  67. }
  68. // -----------------------------------------------------------------------------------
  69. void OggPlayer::Stop() {
  70. ov_clear(&vf);
  71. POS=0;
  72. }
  73. // -----------------------------------------------------------------------------------
  74. int OggPlayer::Seek(int Pos,int mode) {
  75. // convert Pos into samples
  76. int position = 0;
  77. switch(mode) {
  78. case MM_BYTES: position=Pos/(BITS/8)/CHANNELS ; break;
  79. case MM_SAMPLES: position=Pos ; break;
  80. // case MM_MILLISECS: position=Pos*(SAMPLERATE/1000.0) ; break;
  81. }
  82. mmPrint("Ogg seek to:",position);
  83. ogg_int64_t pos = position;
  84. int res = ov_pcm_seek_lap(&vf,pos);
  85. STATUS=1;
  86. POS = pos*((BITS/8)*CHANNELS);
  87. return res;
  88. }
  89. // -----------------------------------------------------------------------------------
  90. extern "C" {
  91. IMaxModMusic* LoadMusic_Ogg(IMaxModStream* Stream) {
  92. mmPrint("OGG Loader...");
  93. OggPlayer* This = new OggPlayer;
  94. This->cb.read_func = readfunc;
  95. This->cb.seek_func = seekfunc;
  96. This->cb.close_func = closefunc;
  97. This->cb.tell_func = tellfunc;
  98. Stream->Seek(0);
  99. if (ov_open_callbacks(Stream,&This->vf,NULL,0,This->cb)<0) {
  100. mmPrint("OGG decoder rejected");
  101. delete This;
  102. return NULL;
  103. }
  104. This->Stream = Stream;
  105. This->SAMPLERATE = ov_info(&This->vf,-1)->rate;
  106. This->CHANNELS = ov_info(&This->vf,-1)->channels;
  107. This->BITS = 16;
  108. This->SIZE = ov_pcm_total(&This->vf,-1)*((This->BITS/8)*This->CHANNELS);
  109. This->SEEKABLE = 1;
  110. This->STATUS = 1;
  111. mmPrint("OGG accepted! samples=",This->SIZE);
  112. mmPrint("channels=",This->CHANNELS);
  113. mmPrint("freq=",This->SAMPLERATE);
  114. return This;
  115. }
  116. }