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

多媒体编程

开发平台:

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 a Creative Labs VOC file into a
  16.     waveform. It's pretty straightforward once you get going. The only
  17.     externally-callable function is Mix_LoadVOC_RW(), which is meant to
  18.     act as identically to SDL_LoadWAV_RW() as possible.
  19.     This file by Ryan C. Gordon (icculus@icculus.org).
  20.     Heavily borrowed from sox v12.17.1's voc.c.
  21.         (http://www.freshmeat.net/projects/sox/)
  22. */
  23. /* $Id: load_voc.c 5214 2009-11-08 17:11:09Z slouken $ */
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include "SDL_mutex.h"
  28. #include "SDL_endian.h"
  29. #include "SDL_timer.h"
  30. #include "SDL_mixer.h"
  31. #include "load_voc.h"
  32. /* Private data for VOC file */
  33. typedef struct vocstuff {
  34. Uint32 rest; /* bytes remaining in current block */
  35. Uint32 rate; /* rate code (byte) of this chunk */
  36. int  silent; /* sound or silence? */
  37. Uint32 srate; /* rate code (byte) of silence */
  38. Uint32 blockseek; /* start of current output block */
  39. Uint32 samples; /* number of samples output */
  40. Uint32 size; /* word length of data */
  41. Uint8  channels; /* number of sound channels */
  42. int     has_extended;       /* Has an extended block been read? */
  43. } vs_t;
  44. /* Size field */ 
  45. /* SJB: note that the 1st 3 are sometimes used as sizeof(type) */
  46. #define ST_SIZE_BYTE 1
  47. #define ST_SIZE_8BIT 1
  48. #define ST_SIZE_WORD 2
  49. #define ST_SIZE_16BIT 2
  50. #define ST_SIZE_DWORD 4
  51. #define ST_SIZE_32BIT 4
  52. #define ST_SIZE_FLOAT 5
  53. #define ST_SIZE_DOUBLE 6
  54. #define ST_SIZE_IEEE 7 /* IEEE 80-bit floats. */
  55. /* Style field */
  56. #define ST_ENCODING_UNSIGNED 1 /* unsigned linear: Sound Blaster */
  57. #define ST_ENCODING_SIGN2 2 /* signed linear 2's comp: Mac */
  58. #define ST_ENCODING_ULAW 3 /* U-law signed logs: US telephony, SPARC */
  59. #define ST_ENCODING_ALAW 4 /* A-law signed logs: non-US telephony */
  60. #define ST_ENCODING_ADPCM 5 /* Compressed PCM */
  61. #define ST_ENCODING_IMA_ADPCM 6 /* Compressed PCM */
  62. #define ST_ENCODING_GSM 7 /* GSM 6.10 33-byte frame lossy compression */
  63. #define VOC_TERM 0
  64. #define VOC_DATA 1
  65. #define VOC_CONT 2
  66. #define VOC_SILENCE 3
  67. #define VOC_MARKER 4
  68. #define VOC_TEXT 5
  69. #define VOC_LOOP 6
  70. #define VOC_LOOPEND 7
  71. #define VOC_EXTENDED    8
  72. #define VOC_DATA_16 9
  73. static int voc_check_header(SDL_RWops *src)
  74. {
  75.     /* VOC magic header */
  76.     Uint8  signature[20];  /* "Creative Voice File32" */
  77.     Uint16 datablockofs;
  78.     SDL_RWseek(src, 0, RW_SEEK_SET);
  79.     if (SDL_RWread(src, signature, sizeof (signature), 1) != 1)
  80.         return(0);
  81.     if (memcmp(signature, "Creative Voice File32", sizeof (signature)) != 0) {
  82.         SDL_SetError("Unrecognized file type (not VOC)");
  83.         return(0);
  84.     }
  85.         /* get the offset where the first datablock is located */
  86.     if (SDL_RWread(src, &datablockofs, sizeof (Uint16), 1) != 1)
  87.         return(0);
  88.     datablockofs = SDL_SwapLE16(datablockofs);
  89.     if (SDL_RWseek(src, datablockofs, RW_SEEK_SET) != datablockofs)
  90.         return(0);
  91.     return(1);  /* success! */
  92. } /* voc_check_header */
  93. /* Read next block header, save info, leave position at start of data */
  94. static int voc_get_block(SDL_RWops *src, vs_t *v, SDL_AudioSpec *spec)
  95. {
  96.     Uint8 bits24[3];
  97.     Uint8 uc, block;
  98.     Uint32 sblen;
  99.     Uint16 new_rate_short;
  100.     Uint32 new_rate_long;
  101.     Uint8 trash[6];
  102.     Uint16 period;
  103.     unsigned int i;
  104.     v->silent = 0;
  105.     while (v->rest == 0)
  106.     {
  107.         if (SDL_RWread(src, &block, sizeof (block), 1) != 1)
  108.             return 1;  /* assume that's the end of the file. */
  109.         if (block == VOC_TERM)
  110.             return 1;
  111.         if (SDL_RWread(src, bits24, sizeof (bits24), 1) != 1)
  112.             return 1;  /* assume that's the end of the file. */
  113.         
  114.         /* Size is an 24-bit value. Ugh. */
  115.         sblen = ( (bits24[0]) | (bits24[1] << 8) | (bits24[2] << 16) );
  116.         switch(block)
  117.         {
  118.             case VOC_DATA:
  119.                 if (SDL_RWread(src, &uc, sizeof (uc), 1) != 1)
  120.                     return 0;
  121.                 /* When DATA block preceeded by an EXTENDED     */
  122.                 /* block, the DATA blocks rate value is invalid */
  123.                 if (!v->has_extended)
  124.                 {
  125.                     if (uc == 0)
  126.                     {
  127.                         SDL_SetError("VOC Sample rate is zero?");
  128.                         return 0;
  129.                     }
  130.                     if ((v->rate != -1) && (uc != v->rate))
  131.                     {
  132.                         SDL_SetError("VOC sample rate codes differ");
  133.                         return 0;
  134.                     }
  135.                     v->rate = uc;
  136.                     spec->freq = (Uint16)(1000000.0/(256 - v->rate));
  137.                     v->channels = 1;
  138.                 }
  139.                 if (SDL_RWread(src, &uc, sizeof (uc), 1) != 1)
  140.                     return 0;
  141.                 if (uc != 0)
  142.                 {
  143.                     SDL_SetError("VOC decoder only interprets 8-bit data");
  144.                     return 0;
  145.                 }
  146.                 v->has_extended = 0;
  147.                 v->rest = sblen - 2;
  148.                 v->size = ST_SIZE_BYTE;
  149.                 return 1;
  150.             case VOC_DATA_16:
  151.                 if (SDL_RWread(src, &new_rate_long, sizeof (new_rate_long), 1) != 1)
  152.                     return 0;
  153.                 new_rate_long = SDL_SwapLE32(new_rate_long);
  154.                 if (new_rate_long == 0)
  155.                 {
  156.                     SDL_SetError("VOC Sample rate is zero?");
  157.                     return 0;
  158.                 }
  159.                 if ((v->rate != -1) && (new_rate_long != v->rate))
  160.                 {
  161.                     SDL_SetError("VOC sample rate codes differ");
  162.                     return 0;
  163.                 }
  164.                 v->rate = new_rate_long;
  165.                 spec->freq = new_rate_long;
  166.                 if (SDL_RWread(src, &uc, sizeof (uc), 1) != 1)
  167.                     return 0;
  168.                 switch (uc)
  169.                 {
  170.                     case 8:  v->size = ST_SIZE_BYTE; break;
  171.                     case 16: v->size = ST_SIZE_WORD; break;
  172.                     default:
  173.                         SDL_SetError("VOC with unknown data size");
  174.                         return 0;
  175.                 }
  176.                 if (SDL_RWread(src, &v->channels, sizeof (Uint8), 1) != 1)
  177.                     return 0;
  178.                 if (SDL_RWread(src, trash, sizeof (Uint8), 6) != 6)
  179.                     return 0;
  180.                 v->rest = sblen - 12;
  181.                 return 1;
  182.             case VOC_CONT:
  183.                 v->rest = sblen;
  184.                 return 1;
  185.             case VOC_SILENCE:
  186.                 if (SDL_RWread(src, &period, sizeof (period), 1) != 1)
  187.                     return 0;
  188.                 period = SDL_SwapLE16(period);
  189.                 if (SDL_RWread(src, &uc, sizeof (uc), 1) != 1)
  190.                     return 0;
  191.                 if (uc == 0)
  192.                 {
  193.                     SDL_SetError("VOC silence sample rate is zero");
  194.                     return 0;
  195.                 }
  196.                 /*
  197.                  * Some silence-packed files have gratuitously
  198.                  * different sample rate codes in silence.
  199.                  * Adjust period.
  200.                  */
  201.                 if ((v->rate != -1) && (uc != v->rate))
  202.                     period = (Uint16)((period * (256 - uc))/(256 - v->rate));
  203.                 else
  204.                     v->rate = uc;
  205.                 v->rest = period;
  206.                 v->silent = 1;
  207.                 return 1;
  208.             case VOC_LOOP:
  209.             case VOC_LOOPEND:
  210.                 for(i = 0; i < sblen; i++)   /* skip repeat loops. */
  211.                 {
  212.                     if (SDL_RWread(src, trash, sizeof (Uint8), 1) != 1)
  213.                         return 0;
  214.                 }
  215.                 break;
  216.             case VOC_EXTENDED:
  217.                 /* An Extended block is followed by a data block */
  218.                 /* Set this byte so we know to use the rate      */
  219.                 /* value from the extended block and not the     */
  220.                 /* data block.                     */
  221.                 v->has_extended = 1;
  222.                 if (SDL_RWread(src, &new_rate_short, sizeof (new_rate_short), 1) != 1)
  223.                     return 0;
  224.                 new_rate_short = SDL_SwapLE16(new_rate_short);
  225.                 if (new_rate_short == 0)
  226.                 {
  227.                    SDL_SetError("VOC sample rate is zero");
  228.                    return 0;
  229.                 }
  230.                 if ((v->rate != -1) && (new_rate_short != v->rate))
  231.                 {
  232.                    SDL_SetError("VOC sample rate codes differ");
  233.                    return 0;
  234.                 }
  235.                 v->rate = new_rate_short;
  236.                 if (SDL_RWread(src, &uc, sizeof (uc), 1) != 1)
  237.                     return 0;
  238.                 if (uc != 0)
  239.                 {
  240.                     SDL_SetError("VOC decoder only interprets 8-bit data");
  241.                     return 0;
  242.                 }
  243.                 if (SDL_RWread(src, &uc, sizeof (uc), 1) != 1)
  244.                     return 0;
  245.                 if (uc)
  246.                     spec->channels = 2;  /* Stereo */
  247.                 /* Needed number of channels before finishing
  248.                    compute for rate */
  249.                 spec->freq = (256000000L/(65536L - v->rate))/spec->channels;
  250.                 /* An extended block must be followed by a data */
  251.                 /* block to be valid so loop back to top so it  */
  252.                 /* can be grabed.                */
  253.                 continue;
  254.             case VOC_MARKER:
  255.                 if (SDL_RWread(src, trash, sizeof (Uint8), 2) != 2)
  256.                     return 0;
  257.                 /* Falling! Falling! */
  258.             default:  /* text block or other krapola. */
  259.                 for(i = 0; i < sblen; i++)
  260.                 {
  261.                     if (SDL_RWread(src, &trash, sizeof (Uint8), 1) != 1)
  262.                         return 0;
  263.                 }
  264.                 if (block == VOC_TEXT)
  265.                     continue;    /* get next block */
  266.         }
  267.     }
  268.     return 1;
  269. }
  270. static int voc_read(SDL_RWops *src, vs_t *v, Uint8 *buf, SDL_AudioSpec *spec)
  271. {
  272.     int done = 0;
  273.     Uint8 silence = 0x80;
  274.     if (v->rest == 0)
  275.     {
  276.         if (!voc_get_block(src, v, spec))
  277.             return 0;
  278.     }
  279.     if (v->rest == 0)
  280.         return 0;
  281.     if (v->silent)
  282.     {
  283.         if (v->size == ST_SIZE_WORD)
  284.             silence = 0x00;
  285.         /* Fill in silence */
  286.         memset(buf, silence, v->rest);
  287.         done = v->rest;
  288.         v->rest = 0;
  289.     }
  290.     else
  291.     {
  292.         done = SDL_RWread(src, buf, 1, v->rest);
  293.         v->rest -= done;
  294.         if (v->size == ST_SIZE_WORD)
  295.         {
  296.             #if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
  297.                 Uint16 *samples = (Uint16 *)buf;
  298.                 for (; v->rest > 0; v->rest -= 2)
  299.                 {
  300.                     *samples = SDL_SwapLE16(*samples);
  301.                     samples++;
  302.                 }
  303.             #endif
  304.             done >>= 1;
  305.         }
  306.     }
  307.     return done;
  308. } /* voc_read */
  309. /* don't call this directly; use Mix_LoadWAV_RW() for now. */
  310. SDL_AudioSpec *Mix_LoadVOC_RW (SDL_RWops *src, int freesrc,
  311.         SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
  312. {
  313.     vs_t v;
  314.     int was_error = 1;
  315.     int samplesize;
  316.     Uint8 *fillptr;
  317.     void *ptr;
  318.     if ( (!src) || (!audio_buf) || (!audio_len) )   /* sanity checks. */
  319.         goto done;
  320.     if ( !voc_check_header(src) )
  321.         goto done;
  322.     v.rate = -1;
  323.     v.rest = 0;
  324.     v.has_extended = 0;
  325.     *audio_buf = NULL;
  326.     *audio_len = 0;
  327.     memset(spec, '', sizeof (SDL_AudioSpec));
  328.     if (!voc_get_block(src, &v, spec))
  329.         goto done;
  330.     if (v.rate == -1)
  331.     {
  332.         SDL_SetError("VOC data had no sound!");
  333.         goto done;
  334.     }
  335.     spec->format = ((v.size == ST_SIZE_WORD) ? AUDIO_S16 : AUDIO_U8);
  336.     if (spec->channels == 0)
  337.         spec->channels = v.channels;
  338.     *audio_len = v.rest;
  339.     *audio_buf = malloc(v.rest);
  340.     if (*audio_buf == NULL)
  341.         goto done;
  342.     fillptr = *audio_buf;
  343.     while (voc_read(src, &v, fillptr, spec) > 0)
  344.     {
  345.         if (!voc_get_block(src, &v, spec))
  346.             goto done;
  347.         *audio_len += v.rest;
  348.         ptr = realloc(*audio_buf, *audio_len);
  349.         if (ptr == NULL)
  350.         {
  351.             free(*audio_buf);
  352.             *audio_buf = NULL;
  353.             *audio_len = 0;
  354.             goto done;
  355.         }
  356.         *audio_buf = ptr;
  357.         fillptr = ((Uint8 *) ptr) + (*audio_len - v.rest);
  358.     }
  359.     spec->samples = (Uint16)(*audio_len / v.size);
  360.     was_error = 0;  /* success, baby! */
  361.     /* Don't return a buffer that isn't a multiple of samplesize */
  362.     samplesize = ((spec->format & 0xFF)/8)*spec->channels;
  363.     *audio_len &= ~(samplesize-1);
  364. done:
  365.     if (src)
  366.     {
  367.         if (freesrc)
  368.             SDL_RWclose(src);
  369.         else
  370.             SDL_RWseek(src, 0, RW_SEEK_SET);
  371.     }
  372.     if ( was_error )
  373.         spec = NULL;
  374.     return(spec);
  375. } /* Mix_LoadVOC_RW */
  376. /* end of load_voc.c ... */