//#define DEBUG #include #include // Generate a .snd file // 44100 samples = 1 second constexpr uint32_t sample_rate = 44100; // CD quality // A table of frequencies indexed by the MIDI note numbers float notes[128]; void init_notes() { for (int i=0; i<128; ++i) notes[i] = pow(2, (i-69)/12.0) * 440.0; } // Some handy macros for hardcoded notes #define C4 (60) #define C4s (61) #define D4 (62) #define D4s (63) #define E4 (64) #define F4 (65) #define F4s (66) #define G4 (67) #define G4s (68) #define A4 (69) #define A4s (70) #define B4 (71) #define C5 (72) #define C5s (73) #define D5 (74) #define D5s (75) #define E5 (76) #define F5 (77) #define F5s (78) #define G5 (79) #define G5s (80) #define A5 (81) #define A5s (82) #define B5 (83) #define C6 (84) /** * Create a .snd file header for a 16-bit, linear PCM, mono * soundfile with a sample rate of 44100 Hz (CD quality) ******************************************************************************/ void write_header() { // send the following values in big-endian format uint32_t magic = htobe32(0x2e736e64); // ".snd" uint32_t data_offset = htobe32(24); // minimal header uint32_t data_size = htobe32(0xffffffff); // length unknown uint32_t encoding = htobe32(3); // 16-bit linear PCM uint32_t rate = htobe32(sample_rate); // samples/sec, 44100 = CD quality uint32_t channels = htobe32(1); // 1 channel = mono std::cout.write((char *)&magic, sizeof(magic)); std::cout.write((char *)&data_offset, sizeof(data_offset)); std::cout.write((char *)&data_size, sizeof(data_size)); std::cout.write((char *)&encoding, sizeof(encoding)); std::cout.write((char *)&rate, sizeof(rate)); std::cout.write((char *)&channels, sizeof(channels)); } /** * Write a mono square wave to stdout. * * @param duration in seconds * @param frequency in Hz * @param amplitude 0 to 1 *****************************************************************************/ void square_wave(float duration, float frequency, float amplitude) { uint32_t num_samples = sample_rate * duration; // total number of samples to generate float period = 1.0/frequency; // time-period of each cycle in seconds float samples_per_period = sample_rate * period; // the number of samples per cycle #ifdef DEBUG std::cerr << "num_samples=" << num_samples << std::endl; std::cerr << "period=" << period << std::endl; std::cerr << "samples_per_period=" << samples_per_period << std::endl; #endif for (uint32_t i=0; i