/project/jni/sdl_mixer/load_ogg.c

https://github.com/aichunyu/FFPlayer · C · 161 lines · 105 code · 31 blank · 25 comment · 18 complexity · aa0d20dcbb868c6414239ac381477f19 MD5 · raw file

  1. /*
  2. SDL_mixer: An audio mixer library based on the SDL library
  3. Copyright (C) 1997-2009 Sam Lantinga
  4. This library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public
  6. License as published by the Free Software Foundation; either
  7. version 2 of the License, or (at your option) any later version.
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Library General Public License for more details.
  12. You should have received a copy of the GNU Library General Public
  13. License along with this library; if not, write to the Free
  14. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  15. This is the source needed to decode an Ogg Vorbis into a waveform.
  16. This file by Vaclav Slavik (vaclav.slavik@matfyz.cz).
  17. */
  18. /* $Id: load_ogg.c 5214 2009-11-08 17:11:09Z slouken $ */
  19. #ifdef OGG_MUSIC
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include "SDL_mutex.h"
  24. #include "SDL_endian.h"
  25. #include "SDL_timer.h"
  26. #include "SDL_mixer.h"
  27. #include "dynamic_ogg.h"
  28. #include "load_ogg.h"
  29. static size_t sdl_read_func(void *ptr, size_t size, size_t nmemb, void *datasource)
  30. {
  31. return SDL_RWread((SDL_RWops*)datasource, ptr, size, nmemb);
  32. }
  33. static int sdl_seek_func(void *datasource, ogg_int64_t offset, int whence)
  34. {
  35. return SDL_RWseek((SDL_RWops*)datasource, (int)offset, whence);
  36. }
  37. static int sdl_close_func_freesrc(void *datasource)
  38. {
  39. return SDL_RWclose((SDL_RWops*)datasource);
  40. }
  41. static int sdl_close_func_nofreesrc(void *datasource)
  42. {
  43. return SDL_RWseek((SDL_RWops*)datasource, 0, RW_SEEK_SET);
  44. }
  45. static long sdl_tell_func(void *datasource)
  46. {
  47. return SDL_RWtell((SDL_RWops*)datasource);
  48. }
  49. /* don't call this directly; use Mix_LoadWAV_RW() for now. */
  50. SDL_AudioSpec *Mix_LoadOGG_RW (SDL_RWops *src, int freesrc,
  51. SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
  52. {
  53. OggVorbis_File vf;
  54. ov_callbacks callbacks;
  55. vorbis_info *info;
  56. Uint8 *buf;
  57. int bitstream = -1;
  58. long samplesize;
  59. long samples;
  60. int read, to_read;
  61. int must_close = 1;
  62. int was_error = 1;
  63. if ( (!src) || (!audio_buf) || (!audio_len) ) /* sanity checks. */
  64. goto done;
  65. if ( !Mix_Init(MIX_INIT_OGG) )
  66. goto done;
  67. callbacks.read_func = sdl_read_func;
  68. callbacks.seek_func = sdl_seek_func;
  69. callbacks.tell_func = sdl_tell_func;
  70. callbacks.close_func = freesrc ?
  71. sdl_close_func_freesrc : sdl_close_func_nofreesrc;
  72. if (vorbis.ov_open_callbacks(src, &vf, NULL, 0, callbacks) != 0)
  73. {
  74. SDL_SetError("OGG bitstream is not valid Vorbis stream!");
  75. goto done;
  76. }
  77. must_close = 0;
  78. info = vorbis.ov_info(&vf, -1);
  79. *audio_buf = NULL;
  80. *audio_len = 0;
  81. memset(spec, '\0', sizeof (SDL_AudioSpec));
  82. spec->format = AUDIO_S16;
  83. spec->channels = info->channels;
  84. spec->freq = info->rate;
  85. spec->samples = 4096; /* buffer size */
  86. samples = (long)vorbis.ov_pcm_total(&vf, -1);
  87. *audio_len = spec->size = samples * spec->channels * 2;
  88. *audio_buf = malloc(*audio_len);
  89. if (*audio_buf == NULL)
  90. goto done;
  91. buf = *audio_buf;
  92. to_read = *audio_len;
  93. #ifdef OGG_USE_TREMOR
  94. for (read = vorbis.ov_read(&vf, (char *)buf, to_read, &bitstream);
  95. read > 0;
  96. read = vorbis.ov_read(&vf, (char *)buf, to_read, &bitstream))
  97. #else
  98. for (read = vorbis.ov_read(&vf, (char *)buf, to_read, 0/*LE*/, 2/*16bit*/, 1/*signed*/, &bitstream);
  99. read > 0;
  100. read = vorbis.ov_read(&vf, (char *)buf, to_read, 0, 2, 1, &bitstream))
  101. #endif
  102. {
  103. if (read == OV_HOLE || read == OV_EBADLINK)
  104. break; /* error */
  105. to_read -= read;
  106. buf += read;
  107. }
  108. vorbis.ov_clear(&vf);
  109. was_error = 0;
  110. /* Don't return a buffer that isn't a multiple of samplesize */
  111. samplesize = ((spec->format & 0xFF)/8)*spec->channels;
  112. *audio_len &= ~(samplesize-1);
  113. done:
  114. if (src && must_close)
  115. {
  116. if (freesrc)
  117. SDL_RWclose(src);
  118. else
  119. SDL_RWseek(src, 0, RW_SEEK_SET);
  120. }
  121. if ( was_error )
  122. spec = NULL;
  123. return(spec);
  124. } /* Mix_LoadOGG_RW */
  125. /* end of load_ogg.c ... */
  126. #endif