반응형

참고: 아래 사이트는 단순음(pure tone, 순음)을 만들 수 있는 서비스를 제공합니다.

 

http://onlinetonegenerator.com/

 

 

 

C 언어로 단순음(pure tone, 순음) 웨이브 파일을 만들기 

 

출처: http://karplus4arduino.wordpress.com/2011/10/08/making-wav-files-from-c-programs/

 

I’m going to try embedding some short pieces of code in this post, and later work out a better way of distributing larger blocks of code.

The code I want to share today consists of a small C file and the associated header for creating WAV files for producing sounds on a laptop or desktop computer. This is not a full-featured WAV file module: the format has a lot of options and I didn’t want the complexity of dealing with all of them. I just wanted to output monophonic sound with a reasonable sampling rate.

 

01 /* make_wav.h
02  * Fri Jun 18 17:06:02 PDT 2010 Kevin Karplus
03  */
04  
05 #ifndef MAKE_WAV_H
06 #define MAKE_WAV_H
07  
08 void write_wav(char * filename, unsigned long num_samples, short int * data, int s_rate);
09     /* open a file named filename, write signed 16-bit values as a
10         monoaural WAV file at the specified sampling rate
11         and close the file
12     */
13  
14 #endif


 

01 /* make_wav.c
02  * Creates a WAV file from an array of ints.
03  * Output is monophonic, signed 16-bit samples
04  * copyright
05  * Fri Jun 18 16:36:23 PDT 2010 Kevin Karplus
06  * Creative Commons license Attribution-NonCommercial
08  */
09  
10 #include <stdio.h>
11 #include <assert.h>
12  
13 #include "make_wav.h"
14  
15 void write_little_endian(unsigned int word, int num_bytes, FILE *wav_file)
16 {
17     unsigned buf;
18     while(num_bytes>0)
19     {   buf = word & 0xff;
20         fwrite(&buf, 1,1, wav_file);
21         num_bytes--;
22         word >>= 8;
23     }
24 }
25  
26 /* information about the WAV file format from
28  */
29  
30 void write_wav(char * filename, unsigned long num_samples, short int * data, int s_rate)
31 {
32     FILE* wav_file;
33     unsigned int sample_rate;
34     unsigned int num_channels;
35     unsigned int bytes_per_sample;
36     unsigned int byte_rate;
37     unsigned long i;    /* counter for samples */
38  
39     num_channels = 1;   /* monoaural */
40     bytes_per_sample = 2;
41  
42     if (s_rate<=0) sample_rate = 44100;
43     else sample_rate = (unsigned int) s_rate;
44  
45     byte_rate = sample_rate*num_channels*bytes_per_sample;
46  
47     wav_file = fopen(filename, "w");
48     assert(wav_file);   /* make sure it opened */
49  
50     /* write RIFF header */
51     fwrite("RIFF", 1, 4, wav_file);
52     write_little_endian(36 + bytes_per_sample* num_samples*num_channels, 4, wav_file);
53     fwrite("WAVE", 1, 4, wav_file);
54  
55     /* write fmt  subchunk */
56     fwrite("fmt ", 1, 4, wav_file);
57     write_little_endian(16, 4, wav_file);   /* SubChunk1Size is 16 */
58     write_little_endian(1, 2, wav_file);    /* PCM is format 1 */
59     write_little_endian(num_channels, 2, wav_file);
60     write_little_endian(sample_rate, 4, wav_file);
61     write_little_endian(byte_rate, 4, wav_file);
62     write_little_endian(num_channels*bytes_per_sample, 2, wav_file);  /* block align */
63     write_little_endian(8*bytes_per_sample, 2, wav_file);  /* bits/sample */
64  
65     /* write data subchunk */
66     fwrite("data", 1, 4, wav_file);
67     write_little_endian(bytes_per_sample* num_samples*num_channels, 4, wav_file);
68     for (i=0; i< num_samples; i++) {
69          write_little_endian((unsigned int)(data[i]),bytes_per_sample, wav_file);
70     }
71  
72     fclose(wav_file);
73 }

 

Note that the above code is not a full program, just a tiny library routine that can be used to generate WAV files. Here is a test program to generate sine waves (inefficiently) to see if the program works. once you have the basic idea, you can write arbitrary programs to generate WAV files and play them back with QuickTime Player, RealPlayer,Audacity, or any of several other sound-playing programs.  This is really old-school computer music, from the days when computers were so slow that quality sounds could not be generated in real time.  It provides a good way to get started in learning the algorithms, though, as you don’t need to worry about efficiency or all the details needed to compute samples and provide them to a DAC at exactly the right rate.

 

01 /* test_make_wav.c
02  * Fri Jun 18 17:13:19 PDT 2010 Kevin Karplus
03  * Test program for the write_wav function in make_wav.c
04  */
05  
06 #include <math.h>
07 #include "make_wav.h"
08  
09 #define S_RATE  (44100)
10 #define BUF_SIZE (S_RATE*2) /* 2 second buffer */
11  
12 int buffer[BUF_SIZE];
13  
14 int main(int argc, char * argv)
15 {
16     int i;
17     float t;
18     float amplitude = 32000;
19     float freq_Hz = 440;
20     float phase=0;
21  
22     float freq_radians_per_sample = freq_Hz*2*M_PI/S_RATE;
23  
24     /* fill buffer with a sine wave */
25     for (i=0; i<BUF_SIZE; i++)
26     {
27         phase += freq_radians_per_sample;
28         buffer[i] = (int)(amplitude * sin(phase));
29     }
30  
31     write_wav("test.wav", BUF_SIZE, buffer, S_RATE);
32  
33     return 0;
34 }

 

반응형

+ Recent posts