VOC.CPP 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. /*
  2. * July 5, 1991
  3. * Copyright 1991 Lance Norskog And Sundry Contributors
  4. * This source code is freely redistributable and may be used for
  5. * any purpose. This copyright notice must be maintained.
  6. * Lance Norskog And Sundry Contributors are not responsible for
  7. * the consequences of using this software.
  8. */
  9. /*
  10. * Sound Tools Sound Blaster VOC handler sources.
  11. *
  12. * Outstanding problem: the Sound Blaster DMA clock is 8 bits wide,
  13. * giving spotty resolution above 10khz. voctartwrite() should check
  14. * the given output rate and make sure it's +-1% what the SB can
  15. * actually do. Other format drivers should do similar checks.
  16. */
  17. #include "st.h"
  18. /* Private data for VOC file */
  19. typedef struct vocstuff {
  20. long rest; /* bytes remaining in current block */
  21. long rate; /* rate code (byte) of this chunk */
  22. int silent; /* sound or silence? */
  23. long srate; /* rate code (byte) of silence */
  24. int blockseek; /* start of current output block */
  25. long samples; /* number of samples output */
  26. } *vs_t;
  27. #define VOC_TERM 0
  28. #define VOC_DATA 1
  29. #define VOC_CONT 2
  30. #define VOC_SILENCE 3
  31. #define VOC_MARKER 4
  32. #define VOC_TEXT 5
  33. #define VOC_LOOP 6
  34. #define VOC_LOOPEND 7
  35. #define min(a, b) (((a) < (b)) ? (a) : (b))
  36. IMPORT int summary, verbose;
  37. void getblock();
  38. vocstartread(ft)
  39. ft_t ft;
  40. {
  41. char header[20];
  42. vs_t v = (vs_t) ft->priv;
  43. int sbseek;
  44. if (! ft->seekable)
  45. fail("VOC input file must be a file, not a pipe");
  46. if (fread(header, 1, 20, ft->fp) != 20)
  47. fail("unexpected EOF in VOC header");
  48. if (strncmp(header, "Creative Voice File\032", 19))
  49. fail("VOC file header incorrect");
  50. sbseek = rlshort(ft);
  51. fseek(ft->fp, sbseek, 0);
  52. v->rate = -1;
  53. v->rest = 0;
  54. getblock(ft);
  55. if (v->rate == -1)
  56. fail("Input .voc file had no sound!");
  57. ft->info.rate = 1000000.0/(256 - v->rate);
  58. ft->info.size = BYTE;
  59. ft->info.style = UNSIGNED;
  60. if (ft->info.channels == -1)
  61. ft->info.channels = 1;
  62. }
  63. vocread(ft, buf, len)
  64. ft_t ft;
  65. long *buf, len;
  66. {
  67. vs_t v = (vs_t) ft->priv;
  68. int done = 0;
  69. if (v->rest == 0)
  70. getblock(ft);
  71. if (v->rest == 0)
  72. return 0;
  73. if (v->silent) {
  74. /* Fill in silence */
  75. for(;v->rest && (done < len); v->rest--, done++)
  76. *buf++ = 0x80000000;
  77. } else {
  78. for(;v->rest && (done < len); v->rest--, done++) {
  79. long l;
  80. if ((l = getc(ft->fp)) == EOF) {
  81. fail("VOC input: short file"); /* */
  82. v->rest = 0;
  83. return 0;
  84. }
  85. l ^= 0x80; /* convert to signed */
  86. *buf++ = LEFT(l, 24);
  87. }
  88. }
  89. return done;
  90. }
  91. /* nothing to do */
  92. vocstopread(ft)
  93. ft_t ft;
  94. {
  95. }
  96. vocstartwrite(ft)
  97. ft_t ft;
  98. {
  99. vs_t v = (vs_t) ft->priv;
  100. if (! ft->seekable)
  101. fail("Output .voc file must be a file, not a pipe");
  102. v->samples = 0;
  103. /* File format name and a ^Z (aborts printing under DOS) */
  104. (void) fwrite("Creative Voice File\032\032", 1, 20, ft->fp);
  105. wlshort(ft, 26); /* size of header */
  106. wlshort(ft, 0x10a); /* major/minor version number */
  107. wlshort(ft, 0x1129); /* checksum of version number */
  108. ft->info.size = BYTE;
  109. ft->info.style = UNSIGNED;
  110. if (ft->info.channels == -1)
  111. ft->info.channels = 1;
  112. }
  113. vocwrite(ft, buf, len)
  114. ft_t ft;
  115. long *buf, len;
  116. {
  117. vs_t v = (vs_t) ft->priv;
  118. unsigned char uc;
  119. v->rate = 256 - (1000000.0/(float)ft->info.rate); /* Rate code */
  120. if (v->samples == 0) {
  121. /* No silence packing yet. */
  122. v->silent = 0;
  123. blockstart(&outformat);
  124. }
  125. v->samples += len;
  126. while(len--) {
  127. uc = RIGHT(*buf++, 24);
  128. uc ^= 0x80;
  129. putc(uc, ft->fp);
  130. }
  131. }
  132. vocstopwrite(ft)
  133. ft_t ft;
  134. {
  135. blockstop(ft);
  136. }
  137. /* Voc-file handlers */
  138. /* Read next block header, save info, leave position at start of data */
  139. void
  140. getblock(ft)
  141. ft_t ft;
  142. {
  143. vs_t v = (vs_t) ft->priv;
  144. unsigned char uc, block;
  145. unsigned long sblen;
  146. int i;
  147. v->silent = 0;
  148. while (v->rest == 0) {
  149. if (feof(ft->fp))
  150. return;
  151. block = getc(ft->fp);
  152. if (block == VOC_TERM)
  153. return;
  154. if (feof(ft->fp))
  155. return;
  156. uc = getc(ft->fp);
  157. sblen = uc;
  158. uc = getc(ft->fp);
  159. sblen |= ((long) uc) << 8;
  160. uc = getc(ft->fp);
  161. sblen |= ((long) uc) << 16;
  162. switch(block) {
  163. case VOC_DATA:
  164. uc = getc(ft->fp);
  165. if (uc == 0)
  166. fail("File %s: Sample rate is zero?");
  167. if ((v->rate != -1) && (uc != v->rate))
  168. fail("File %s: sample rate codes differ: %d != %d",
  169. v->rate, uc);
  170. v->rate = uc;
  171. uc = getc(ft->fp);
  172. if (uc != 0)
  173. fail("File %s: only interpret 8-bit data!");
  174. v->rest = sblen - 2;
  175. return;
  176. case VOC_CONT:
  177. v->rest = sblen;
  178. return;
  179. case VOC_SILENCE:
  180. {
  181. unsigned short period;
  182. period = rlshort(ft);
  183. uc = getc(ft->fp);
  184. if (uc == 0)
  185. fail("File %s: Silence sample rate is zero");
  186. /*
  187. * Some silence-packed files have gratuitously
  188. * different sample rate codes in silence.
  189. * Adjust period.
  190. */
  191. if ((v->rate != -1) && (uc != v->rate))
  192. period = (period * (256 - uc))/(256 - v->rate);
  193. else
  194. v->rate = uc;
  195. v->rest = period;
  196. v->silent = 1;
  197. return;
  198. }
  199. case VOC_MARKER:
  200. uc = getc(ft->fp);
  201. uc = getc(ft->fp);
  202. /* Falling! Falling! */
  203. case VOC_TEXT:
  204. {
  205. int i;
  206. /* Could add to comment in SF? */
  207. for(i = 0; i < sblen; i++)
  208. getc(ft->fp);
  209. }
  210. continue; /* get next block */
  211. case VOC_LOOP:
  212. case VOC_LOOPEND:
  213. report("File %s: skipping repeat loop");
  214. for(i = 0; i < sblen; i++)
  215. getc(ft->fp);
  216. break;
  217. default:
  218. report("File %s: skipping unknown block code %d",
  219. ft->filename, block);
  220. for(i = 0; i < sblen; i++)
  221. getc(ft->fp);
  222. }
  223. }
  224. }
  225. /* Start an output block. */
  226. blockstart(ft)
  227. ft_t ft;
  228. {
  229. vs_t v = (vs_t) ft->priv;
  230. v->blockseek = ftell(ft->fp);
  231. if (v->silent) {
  232. putc(VOC_SILENCE, ft->fp); /* Silence block code */
  233. putc(0, ft->fp); /* Period length */
  234. putc(0, ft->fp); /* Period length */
  235. putc((int) v->rate, ft->fp); /* Rate code */
  236. } else {
  237. putc(VOC_DATA, ft->fp); /* Voice Data block code */
  238. putc(0, ft->fp); /* block length (for now) */
  239. putc(0, ft->fp); /* block length (for now) */
  240. putc(0, ft->fp); /* block length (for now) */
  241. putc((int) v->rate, ft->fp); /* Rate code */
  242. putc(0, ft->fp); /* 8-bit raw data */
  243. }
  244. }
  245. /* End the current data or silence block. */
  246. blockstop(ft)
  247. ft_t ft;
  248. {
  249. vs_t v = (vs_t) ft->priv;
  250. long datum;
  251. putc(0, ft->fp); /* End of file block code */
  252. fseek(ft->fp, v->blockseek, 0); /* seek back to block length */
  253. fseek(ft->fp, 1, 1); /* seek forward one */
  254. if (v->silent) {
  255. datum = (v->samples) & 0xff;
  256. putc((int)datum, ft->fp); /* low byte of length */
  257. datum = (v->samples >> 8) & 0xff;
  258. putc((int)datum, ft->fp); /* high byte of length */
  259. } else {
  260. v->samples += 2; /* adjustment: SBDK pp. 3-5 */
  261. datum = (v->samples) & 0xff;
  262. putc((int)datum, ft->fp); /* low byte of length */
  263. datum = (v->samples >> 8) & 0xff;
  264. putc((int)datum, ft->fp); /* middle byte of length */
  265. datum = (v->samples >> 16) & 0xff;
  266. putc((int)datum, ft->fp); /* high byte of length */
  267. }
  268. }