Introduction
Introduction Statistics Contact Development Disclaimer Help
tFirst commit - cynth - modular musical synthesizer using POSIX streams
git clone git://src.adamsgaard.dk/cynth
Log
Files
Refs
LICENSE
---
commit a4e55f71b09f1349db5c9148cea5d5cc0ab20138
Author: Anders Damsgaard Christensen <[email protected]>
Date: Thu, 16 Aug 2012 22:14:12 +0200
First commit
Diffstat:
A Makefile | 18 ++++++++++++++++++
A README.rst | 4 ++++
A seq-data/bass.txt | 16 ++++++++++++++++
A seq-data/lead.txt | 36 +++++++++++++++++++++++++++++…
A src/freq.h | 23 +++++++++++++++++++++++
A src/osc.c | 102 +++++++++++++++++++++++++++++…
A src/oscillators.c | 170 +++++++++++++++++++++++++++++…
A src/oscillators.h | 27 +++++++++++++++++++++++++++
A src/sndconf.h | 37 +++++++++++++++++++++++++++++…
9 files changed, 433 insertions(+), 0 deletions(-)
---
diff --git a/Makefile b/Makefile
t@@ -0,0 +1,18 @@
+CFLAGS=-O2 -Wall
+LDLIBS=-lm
+
+cynth: osc
+
+osc: src/osc.o src/oscillators.o
+ $(CC) $(LDLIBS) $^ -o $@
+
+clean:
+ $(RM) osc src/*.o
+
+edit:
+ $(EDITOR) -p Makefile src/*.c src/*.h
+
+test-osc: osc
+ @#./$< | aplay -c 1 -f S16_LE -r 44100
+ ./$< -c 1 -r 44100 | aplay -c 1 -r 44100
+ @#./$< | aplay
diff --git a/README.rst b/README.rst
t@@ -0,0 +1,4 @@
+CYNTH - A modular software synthesizer after the POSIX philosophy
+=================================================================
+
+
diff --git a/seq-data/bass.txt b/seq-data/bass.txt
t@@ -0,0 +1,16 @@
+220.0 0.5
+220.0 0.5
+261.626 0.5
+195.998 0.5
+220.0 0.5
+220.0 0.5
+261.626 0.5
+195.998 0.5
+220.0 0.5
+220.0 0.5
+261.626 0.5
+195.998 0.5
+220.0 0.5
+220.0 0.5
+261.626 0.5
+195.998 0.5
diff --git a/seq-data/lead.txt b/seq-data/lead.txt
t@@ -0,0 +1,36 @@
+880.00 0.04167
+440.00 0.04167
+220.00 0.04167
+880.00 0.04167
+440.00 0.04167
+220.00 0.04167
+880.00 0.04167
+440.00 0.04167
+220.00 0.04167
+880.00 0.04167
+440.00 0.04167
+220.00 0.04167
+880.00 0.25
+783.991 0.25
+880.00 0.25
+783.991 0.25
+1046.50 0.25
+0.0 1.00
+783.991 0.25
+880.00 0.25
+783.991 0.25
+1046.50 0.25
+0.0 0.25
+440.000 0.25
+659.255 0.25
+880.000 0.25
+783.991 0.25
+880.000 0.25
+783.991 0.25
+1046.50 0.25
+0.0 1.00
+783.991 0.25
+880.00 0.25
+783.991 0.25
+523.251 0.25
+0.0 0.25
diff --git a/src/freq.h b/src/freq.h
t@@ -0,0 +1,23 @@
+#ifndef FREQ_H_
+#define FREQ_H_
+
+/* Scientific name converted to key number */
+enum notes { A0 = 1, As0, B0,
+ C1, Cs1, D1, Ds1, E1, F1, Fs1, G1, Gs1, A1, As1, B1,
+ C2, Cs2, D2, Ds2, E2, F2, Fs2, G2, Gs2, A2, As2, B2,
+ C3, Cs3, D3, Ds3, E3, F3, Fs3, G3, Gs3, A3, As3, B3,
+ C4, Cs4, D4, Ds4, E4, F4, Fs4, G4, Gs4, A4, As4, B4,
+ C5, Cs5, D5, Ds5, E5, F5, Fs5, G5, Gs5, A5, As5, B5,
+ C6, Cs6, D6, Ds6, E6, F6, Fs6, G6, Gs6, A6, As6, B6,
+ C7, Cs7, D7, Ds7, E7, F7, Fs7, G7, Gs7, A7, As7, B7,
+ C8, Cs8, D8, Ds8, E8, F8, Fs8, G8, Gs8, A8, As8, B8 };
+
+/* Returns frequencies of notes in twelve-tone equal temperament
+ * C4 = 40, A4 = 49
+ * See: https://en.wikipedia.org/wiki/Piano_key_frequencies */
+inline float freq(int n)
+{
+ return pow(2.0,(float)(n-49)/12.0) * 440.0;
+}
+
+#endif
diff --git a/src/osc.c b/src/osc.c
t@@ -0,0 +1,102 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include "sndconf.h"
+#include "oscillators.h"
+
+
+
+/*** Main ***/
+int main(int argc, char* argv[])
+{
+ /* Pointer to wave-generating function */
+ float (*fwave)(float, float, float) = &sine;
+
+ /* Pointer to oscillator function */
+ void (*fosc)(float(*fwave)(float, float, float), float, float, float) = &osc…
+
+ /* Sound configuration structure, containing default values */
+ sndparams.channels = 1;
+ sndparams.rate = 8000;
+ sndparams.write_wave = 0;
+
+ /* Oscillator volume */
+ float vol = 0.4f;
+
+ /* File pointer */
+ FILE* fp = stdin;
+
+ /* Display help if requested */
+ if (argc == 2 && (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") ==…
+ printf("%s: cynth oscillator\n", argv[0]);
+ printf("Usage: %s [OPTION]... [FILE]\nOptions:\n", argv[0]);
+ printf("-h, --help\t\thelp\n");
+ printf("-w, --waveform TYPE\twaveform (sine (default), square, triangle, s…
+ printf("-h16, --harmonics16\tadd 16 upper harmonics\n");
+ printf("-V, --volume\t\toscillator volume [0.0;1.0] (default 0.4)\n");
+ printf("-c, --channels\tnumber of channels (default 1)\n");
+ printf("-f, --format\t\tsample format (U8 (default) or U16_LE)\n");
+ printf("-r, --rate\t\tsample rate [Hz] (default 8000)\n");
+ printf("-W, --writewate\tsave waveform to wave.dat\n");
+ printf("If FILE is not specified, input will be read from stdin.\n");
+ return 0; /* Exit with success */
+ }
+
+ /* Process input parameters */
+ int i;
+ for (i = 1; i < argc; ++i) { /* Skip argv[0] */
+
+ /* Waveform specified */
+ if (strcmp(argv[i], "-w") == 0 || strcmp(argv[i], "--waveform") == 0) {
+ if (strcmp(argv[i+1], "square") == 0) {
+ fwave = &square; ++i;
+ } else if (strcmp(argv[i+1], "triangle") == 0) {
+ fwave = &triangle; ++i;
+ } else if (strcmp(argv[i+1], "saw") == 0) {
+ fwave = &saw; ++i;
+ }
+
+ /* Use different oscillator function */
+ } else if (strcmp(argv[i], "-h16") == 0 || strcmp(argv[i], "--harmonics16"…
+ fosc = &osc_mono_16h;
+
+ /* Set oscillator volume */
+ } else if (strcmp(argv[i], "-V") == 0 || strcmp(argv[i], "--volume") == 0)…
+ vol = atof(argv[i+1]); ++i;
+
+ /* Set number of channels */
+ } else if (strcmp(argv[i], "-c") == 0 || strcmp(argv[i], "--channels") == …
+ sndparams.channels = atoi(argv[i+1]); ++i;
+
+ /* Set sample format */
+ } else if (strcmp(argv[i], "-f") == 0 || strcmp(argv[i], "--format") == 0)…
+ if (strcmp(argv[i+1], "U16_LE") == 0)
+ ;/*typedef unsigned short FORMAT_TYPE; ++i;*/
+
+ /* Set sample rate */
+ } else if (strcmp(argv[i], "-r") == 0 || strcmp(argv[i], "--rate") == 0) {
+ sndparams.rate = atoi(argv[i+1]); ++i;
+
+ /* Write waveform to wave.dat */
+ } else if (strcmp(argv[i], "-W") == 0 || strcmp(argv[i], "--writewave") ==…
+ sndparams.write_wave = 1;
+
+ /* File given as input argument */
+ } else if (i == argc-1) {
+ if ((fp = fopen(argv[i], "r")) == NULL) {
+ fprintf(stderr, "%s: Can't open %s for read\n", argv[0], argv[i]);
+ exit(1); /* Exit with error */
+ }
+ }
+ }
+
+ /* Read input data, line by line and call oscillator function */
+ float freq, time;
+ while (!feof(fp) && fscanf(fp, "%f\t%f", &freq, &time) == 2) {
+ fosc(fwave, freq, time, vol);
+ }
+
+ /* Flush buffers and return successfully */
+ exit(0);
+}
diff --git a/src/oscillators.c b/src/oscillators.c
t@@ -0,0 +1,170 @@
+#include <stdio.h>
+#include <math.h>
+#include <limits.h>
+#include "oscillators.h"
+#include "sndconf.h"
+
+/* Save wave position between functions */
+float phi;
+
+/* Hard-clip indicator */
+int clip = 0;
+
+/* Hard limit volume to sample format limits */
+float limit(float y)
+{
+ if (y < FORMAT_MIN) {
+ y = FORMAT_MIN;
+ if (clip == 0) {
+ fprintf(stderr, "Sample format upper limit exceeded: Hard-clipping\n");
+ clip = 1;
+ }
+ } else if (y > FORMAT_MAX) {
+ y = FORMAT_MAX;
+ if (clip == 0) {
+ fprintf(stderr, "Sample format lower limit exceeded: Hard-clipping\n");
+ clip = 1;
+ }
+ }
+ return y;
+}
+
+/* Sine wave generator */
+float sine(float A, float omega, float t)
+{
+ return A * sin(omega * t + phi);
+}
+
+/* Square wave generator */
+float square(float A, float omega, float t)
+{
+ if (sin(omega * t + phi) > 0.0f)
+ return A;
+ else
+ return -A;
+}
+
+/* Triangle wave generator */
+float triangle(float A, float omega, float t)
+{
+ return A * asin(sin(omega * t + phi)) / (M_PI / 2.0f);
+}
+
+/* Sawtooth wave generator */
+float saw(float A, float omega, float t)
+{
+ /* Calculate period */
+ float T = 2.0f * M_PI / omega;
+
+/* return (t/T - floor(t/T)) * A; */
+ return ((t/T - floor(t/T)) - 0.5f) * A;
+}
+
+
+/* Input arg: frequency */
+void osc_mono(float (*osc)(float A, float omega, float t),
+ float freq, float time, float volume)
+{
+ FILE *fp = NULL;
+
+ /* Midpoint of bandwith */
+ const FORMAT_TYPE mid = (FORMAT_MAX + FORMAT_MIN)/2;
+
+ /* Amplitude */
+ const float A = (float)mid * volume;
+
+ /* Current time */
+ float t;
+
+ /* Position of wave at t */
+ float y = 0;
+
+ /* Angular frequency [rad/s] of 1st harmonic */
+ const float omega = 2.0f * M_PI * freq;
+
+ if (sndparams.write_wave == 1) {
+ fp = fopen("wave.dat", "w");
+ }
+
+ for (t = 0.0f; t < time; t += 1.0/sndparams.rate) {
+ y = mid;
+
+ /* Fundamental tone */
+ y += osc(A, omega, t);
+
+ /* Write wave position to stdout for aplay */
+ y = limit(y); /* Hard-clip signal to limits */
+ putchar((FORMAT_TYPE)y);
+
+ if (sndparams.write_wave == 1)
+ fprintf(fp, "%f\t%f\n", t, y);
+ }
+
+ if (sndparams.write_wave == 1)
+ fclose(fp);
+
+ /* Unlock clipping indicator */
+ clip = 0;
+
+ /* Save wave position for next oscillator call */
+ phi = y;
+}
+
+/* Input arg: frequency */
+void osc_mono_16h(float (*osc)(float A, float omega, float t),
+ float freq, float time, float volume)
+{
+ FILE *fp = NULL;
+
+ /* Midpoint of bandwith */
+ const FORMAT_TYPE mid = (FORMAT_MAX + FORMAT_MIN)/2;
+
+ /* Amplitude */
+ const float A = (float)mid * volume;
+
+ /* Current time */
+ float t;
+
+ /* Position of wave at t */
+ float y = 0;
+
+ /* Angular frequency [rad/s] of 1st harmonic */
+ const float omega = 2.0f * M_PI * freq;
+
+ if (sndparams.write_wave == 1) {
+ fp = fopen("wave.dat", "w");
+ }
+
+ /* Overtone counter */
+ int o;
+
+ for (t = 0.0f; t < time; t += 1.0/sndparams.rate) {
+ y = mid;
+
+ /* Fundamental tone */
+ y += osc(A, omega, t);
+
+ /* Create 16 orders of overtones */
+ float vol = 0.2f; /* Vol. of first harmonic */
+ for (o = 2; o<17; ++o) {
+ y += osc(A*vol, omega*(float)o, t);
+ }
+
+ /* Write wave position to stdout for aplay */
+ y = limit(y); /* Hard-clip signal to limits */
+ putchar((FORMAT_TYPE)y);
+
+ if (sndparams.write_wave == 1)
+ fprintf(fp, "%f\t%f\n", t, y);
+ }
+
+ if (sndparams.write_wave == 1)
+ fclose(fp);
+
+ /* Unlock clipping indicator */
+ clip = 0;
+
+ /* Save wave position for next oscillator call */
+ phi = y;
+}
+
diff --git a/src/oscillators.h b/src/oscillators.h
t@@ -0,0 +1,27 @@
+#ifndef OSCILLATORS_H_
+#define OSCILLATORS_H_
+
+
+/**** WAVEFORM FUNCTIONS, USED BY OSCILLATORS ****/
+float sine(float A, float omega, float t);
+float square(float A, float omega, float t);
+float triangle(float A, float omega, float t);
+float saw(float A, float omega, float t);
+
+
+
+/**** OSCILLATORS ****/
+
+/* Mono oscillator */
+void osc_mono(float (*osc)(float A, float omega, float t), /* Waveform functio…
+ float freq, /* Frequency of fundamental tone */
+ float time, /* Duration of note */
+ float volume); /* Linear volume, [0;1] */
+
+/* Mono oscillator with 16 upper harmonics */
+void osc_mono_16h(float (*osc)(float A, float omega, float t), /* Waveform fun…
+ float freq, /* Frequency of fundamental …
+ float time, /* Duration of note */
+ float volume); /* Linear volume, [0;1] */
+
+#endif
diff --git a/src/sndconf.h b/src/sndconf.h
t@@ -0,0 +1,37 @@
+#ifndef SNDCONF_H_
+#define SNDCONF_H_
+
+
+/* Sample format (see `man aplay`)
+ * Define lower and upper values of the format integral types */
+/**/
+typedef unsigned char FORMAT_TYPE;
+#define FORMAT_MIN 0
+#define FORMAT_MAX UCHAR_MAX
+/*
+typedef unsigned short FORMAT_TYPE;
+#define FORMAT_MIN 0
+#define FORMAT_MAX USHRT_MAX
+*/
+
+
+/*** Default values of sound device parameters ***/
+struct sndconf {
+
+ /* Channels: 1-32
+ * 1: Mono (default)
+ * 2: Stereo */
+ int channels;
+
+ /* Sample rate: 2000-192000 Hz
+ * Times per second to produce a value */
+ int rate;
+
+ /* Write waveform to file:
+ * 0: No
+ * 1: Yes */
+ int write_wave;
+
+} sndparams;
+
+#endif
You are viewing proxied material from mx1.adamsgaard.dk. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.