misc_wav.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. /*
  2. misc_wav.c
  3. Copyright (c) 2004 NoisyB
  4. This library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 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. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with this library; if not, write to the Free Software
  14. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  15. */
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <math.h>
  19. #include "misc.h"
  20. #include "misc_wav.h"
  21. #ifndef M_PI
  22. #define M_PI 3.1415926535
  23. #endif
  24. // TODO: replace ceil(), floor() and sin()
  25. #if 0
  26. unsigned char wav_header[3][80] = {
  27. {
  28. 'R', 'I', 'F', 'F', 0x80, 0x80, 0x80, 0x80, // RIFF TAG
  29. 'W', 'A', 'V', 'E', // WAV TAG
  30. 'f', 'm', 't', ' ', 0x10, 0, 0, 0, // FMT TAG
  31. 1, 0, // format (WAVE_FORMAT_PCM)
  32. 1, 0, // CHANNELS
  33. 0x22, 0x56, 0, 0, // SamplesPerSec
  34. 0x22, 0x56, 0, 0, // BytesPerSec
  35. 1, 0, // Block align
  36. 8, 0, // Bits per sample
  37. 'd', 'a', 't', 'a', 0, 0, 0, 0, '\0' // DATA TAG
  38. },
  39. {
  40. 'R', 'I', 'F', 'F', 0x80, 0x80, 0x80, 0x80, // RIFF TAG
  41. 'W', 'A', 'V', 'E', // WAV TAG
  42. 'f', 'm', 't', ' ', 0x10, 0, 0, 0, // FMT TAG
  43. 1, 0, // format (WAVE_FORMAT_PCM)
  44. 1, 0, // CHANNELS
  45. 0x44, 0xac, 0, 0, // SamplesPerSec
  46. 0x44, 0xac, 0, 0, // BytesPerSec
  47. 1, 0, // Block align
  48. 8, 0, // Bits per sample
  49. 'd', 'a', 't', 'a', 0, 0, 0, 0, '\0' // DATA TAG
  50. },
  51. {
  52. 'R', 'I', 'F', 'F', 0x80, 0x80, 0x80, 0x80, // RIFF TAG
  53. 'W', 'A', 'V', 'E', // WAV TAG
  54. 'f', 'm', 't', ' ', 0x10, 0, 0, 0, // FMT TAG
  55. 1, 0, // format (WAVE_FORMAT_PCM)
  56. 2, 0, // CHANNELS
  57. 0x44, 0xac, 0, 0, // SamplesPerSec
  58. 0x10, 0xb1, 2, 0, // BytesPerSec
  59. 4, 0, // Block align
  60. 0x10, 0, // Bits per sample
  61. 'd', 'a', 't', 'a', 0, 0, 0, 0, '\0' // DATA TAG
  62. }
  63. };
  64. #endif
  65. typedef struct
  66. {
  67. uint8_t magic[4]; // 'RIFF'
  68. uint32_t total_length; // length of file minus the 8 byte riff header
  69. uint8_t type[4]; // 'WAVE'
  70. uint8_t fmt[4]; // 'fmt '
  71. uint32_t header_length; // length of format chunk minus 8 byte header
  72. uint16_t format; // identifies WAVE_FORMAT_PCM
  73. uint16_t channels;
  74. uint32_t freq; // samples per second per channel
  75. uint32_t bytespersecond;
  76. uint16_t blockalign; // basic block size
  77. uint16_t bitspersample;
  78. // PCM formats then go straight to the data chunk
  79. uint8_t data[4]; // 'data'
  80. uint32_t data_length; // length of data chunk minus 8 byte header
  81. } st_wav_header_t;
  82. int
  83. misc_wav_write_header (FILE *fh, int channels, int freq,
  84. int bytespersecond, int blockalign,
  85. int bitspersample, int data_length)
  86. {
  87. st_wav_header_t wav_header;
  88. memset (&wav_header, 0, sizeof (st_wav_header_t));
  89. strncpy ((char *) wav_header.magic, "RIFF", 4);
  90. wav_header.total_length = me2le_32 (data_length + sizeof (st_wav_header_t) - 8);
  91. strncpy ((char *) wav_header.type, "WAVE", 4);
  92. strncpy ((char *) wav_header.fmt, "fmt ", 4);
  93. wav_header.header_length = me2le_32 (16); // always 16
  94. wav_header.format = me2le_16 (1); // WAVE_FORMAT_PCM == default
  95. wav_header.channels = (uint16_t) me2le_16 (channels);
  96. wav_header.freq = me2le_32 (freq);
  97. wav_header.bytespersecond = me2le_32 (bytespersecond);
  98. wav_header.blockalign = (uint16_t) me2le_16 (blockalign);
  99. wav_header.bitspersample = (uint16_t) me2le_16 (bitspersample);
  100. strncpy ((char *) wav_header.data, "data", 4);
  101. wav_header.data_length = me2le_32 (data_length);
  102. return fwrite (&wav_header, 1, sizeof (st_wav_header_t), fh);
  103. }
  104. void
  105. misc_wav_generator (unsigned char *bit, int bitLength, float volume, int wavType)
  106. {
  107. int i;
  108. #ifndef USE_LIBMATH
  109. (void) wavType;
  110. #else
  111. if (wavType == SQUARE_WAVE)
  112. #endif // USE_LIBMATH
  113. {
  114. int halfBitLength = (int) (floor ((float) bitLength) / 2.0);
  115. int isOdd = (int) (ceil ((float) bitLength / 2.0) - halfBitLength);
  116. for (i = 0; i < halfBitLength; i++)
  117. bit[i] = (unsigned char) floor (0xfc * volume);
  118. if (isOdd)
  119. bit[i++] = 0x80;
  120. for (; i < bitLength; i++)
  121. bit[i] = (unsigned char) floor (0x06 * volume);
  122. }
  123. #ifdef USE_LIBMATH
  124. else // SINE_WAV
  125. for (i = 0; i < bitLength; i++)
  126. bit[i] = (unsigned char) floor
  127. (((sin ((((double) 2 * (double) M_PI) / (double) bitLength) * (double) i) * volume + 1) * 128));
  128. #endif // USE_LIBMATH
  129. }