#include #include #include #include #include #include #include #include #define UNIT_PITCH 2546.48 #define BASE_PITCH 440.0 int16_t generate_sample(int phase, double pitch) { double result = 0; int i; for (i = 1; i <= 8; i++) { result += 1.0/(i*i)*sin(phase*pitch/UNIT_PITCH*i); } return result*10000; } /* A note is a 32-bit value used as follows: the least significant 8 bits are a number of octaves the next 8 bits are a number of fifths the next 8 bits are a number of thirds */ double pitch(uint32_t note) { signed char octave = note; signed char fifth = (note >> 8); signed char third = (note >> 16); return BASE_PITCH * pow(2.0, octave) * pow(0.75, fifth) * pow(1.25, third); } uint32_t next(uint32_t prev, uint32_t base, double core_pitch, int m) { signed char octave = prev; signed char fifth = (prev >> 8); signed char third = (prev >> 16); signed char bo = base; signed char bf = (base >> 8); signed char bt = (base >> 16); int pdo = 125; int pio = 125; int pdf = 160; int pif = 160; int pdt = 80; int pit = 80; if (pitch(prev) < core_pitch / 2) { pio += 180; pdo -= 90; } if (pitch(prev) > core_pitch / 2) { pdo += 180; pio -= 90; } if (fifth < bf) { pif += (m ? 120 : 240); pdf -= (m ? 60 : 120); } if (bf < fifth) { pdf += (m ? 120 : 240); pif -= (m ? 60 : 120); } if (third < bt) { pit += (m ? 160 : 240); pdt -= 80; } if (bt < third) { pdt += (m ? 160 : 240); pit -= 80; } int r = rand() % 1000; if (r < pdo) octave--; else if (r < pdo + pio) octave++; else if (r < pdo + pio + pdf) fifth--; else if (r < pdo + pio + pdf + pif) fifth++; else if (r < pdo + pio + pdf + pif + pdt) third--; else if (r < pdo + pio + pdf + pif + pdt + pit) third++; return (uint32_t)(unsigned char)octave | ((uint32_t)(unsigned char)fifth << 8) | ((uint32_t)(unsigned char)third << 16); } int main() { srand(time(NULL)); int i, out; out = open("/dev/dsp", O_WRONLY); if (out < 0) { perror("Could not open /dev/dsp: "); return 1; } int format = AFMT_S16_NE; if (ioctl(out, SNDCTL_DSP_SETFMT, &format) == -1) { perror("Could not set audio format: "); return 1; } if (format != AFMT_S16_LE) { fprintf(stderr, "Your sound-card does not support signed 16-bit native-endian audio"); return 1; } int speed = 16000; if (ioctl(out, SNDCTL_DSP_SPEED, &speed) == -1) { perror("Could not set audio format: "); return 1; } if (speed < 15500 || speed > 16500) { fprintf(stderr, "Your sound-card does not support 16kHz audio"); return 1; } uint32_t root = 0; uint32_t bass = -1; uint32_t cp1 = 0; uint32_t cp2 = 0; int d1 = 1; int d2 = 1; int d3 = 1; int16_t data[1000]; while (1) { root = next(root, 0, 440.0, 0); for (i = 0; i < 64000; i++) { if (i % 16000 == 0) { d1--; if (d1 == 0) { int m = i / 16000; bass = next(bass, root, 220.0, m); d1 = rand()%(4-m)+1; } } if (i % 8000 == 0) { d2--; if (d2 == 0) { int m = i % 32000 / 8000; cp1 = next(cp1, bass, 330.0, m); d2 = rand()%(4-m)+1; } } if (i % 4000 == 0) { d3--; if (d3 == 0) { int m = i % 16000 / 4000; cp2 = next(cp2, bass, 440.0, m); d3 = rand()%(4-m)+1; } } data[i%1000] = generate_sample(i, pitch(bass)) + generate_sample(i, pitch(cp1)) + generate_sample(i, pitch(cp2)); if (i % 1000 == 999) { if (write(out, data, 2000) < 0) { perror("Could not write to /dev/dsp: "); return 1; } } } } close(out); }