load_ogg.c
上传用户:nini_0081
上传日期:2022-07-21
资源大小:2628k
文件大小:4k
源码类别:

多媒体编程

开发平台:

DOS

  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.     
  64.     if ( (!src) || (!audio_buf) || (!audio_len) )   /* sanity checks. */
  65.         goto done;
  66.     if ( !Mix_Init(MIX_INIT_OGG) )
  67.         goto done;
  68.     callbacks.read_func = sdl_read_func;
  69.     callbacks.seek_func = sdl_seek_func;
  70.     callbacks.tell_func = sdl_tell_func;
  71.     callbacks.close_func = freesrc ? 
  72.                            sdl_close_func_freesrc : sdl_close_func_nofreesrc;
  73.     if (vorbis.ov_open_callbacks(src, &vf, NULL, 0, callbacks) != 0)
  74.     {
  75.         SDL_SetError("OGG bitstream is not valid Vorbis stream!");
  76.         goto done;
  77.     }
  78.     must_close = 0;
  79.     
  80.     info = vorbis.ov_info(&vf, -1);
  81.     
  82.     *audio_buf = NULL;
  83.     *audio_len = 0;
  84.     memset(spec, '', sizeof (SDL_AudioSpec));
  85.     spec->format = AUDIO_S16;
  86.     spec->channels = info->channels;
  87.     spec->freq = info->rate;
  88.     spec->samples = 4096; /* buffer size */
  89.     
  90.     samples = (long)vorbis.ov_pcm_total(&vf, -1);
  91.     *audio_len = spec->size = samples * spec->channels * 2;
  92.     *audio_buf = malloc(*audio_len);
  93.     if (*audio_buf == NULL)
  94.         goto done;
  95.     buf = *audio_buf;
  96.     to_read = *audio_len;
  97. #ifdef OGG_USE_TREMOR
  98.     for (read = vorbis.ov_read(&vf, (char *)buf, to_read, &bitstream);
  99.  read > 0;
  100.  read = vorbis.ov_read(&vf, (char *)buf, to_read, &bitstream))
  101. #else
  102.     for (read = vorbis.ov_read(&vf, (char *)buf, to_read, 0/*LE*/, 2/*16bit*/, 1/*signed*/, &bitstream);
  103.          read > 0;
  104.          read = vorbis.ov_read(&vf, (char *)buf, to_read, 0, 2, 1, &bitstream))
  105. #endif  
  106.     {
  107.         if (read == OV_HOLE || read == OV_EBADLINK)
  108.             break; /* error */
  109.         
  110.         to_read -= read;
  111.         buf += read;
  112.     }
  113.     vorbis.ov_clear(&vf);
  114.     was_error = 0;
  115.     /* Don't return a buffer that isn't a multiple of samplesize */
  116.     samplesize = ((spec->format & 0xFF)/8)*spec->channels;
  117.     *audio_len &= ~(samplesize-1);
  118. done:
  119.     if (src && must_close)
  120.     {
  121.         if (freesrc)
  122.             SDL_RWclose(src);
  123.         else
  124.             SDL_RWseek(src, 0, RW_SEEK_SET);
  125.     }
  126.     if ( was_error )
  127.         spec = NULL;
  128.     return(spec);
  129. } /* Mix_LoadOGG_RW */
  130. /* end of load_ogg.c ... */
  131. #endif