initial commit

master
vampirefrog 6 years ago
commit 525c1d7f09

@ -0,0 +1 @@
#define SAMPLE_RATE 48000

261
main.c

@ -0,0 +1,261 @@
/*
Copyright (C) 2002 Anthony Van Groningen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <math.h>
#include <getopt.h>
#include <string.h>
#include <jack/jack.h>
#include <jack/transport.h>
#include <asoundlib.h>
#include "synth.h"
struct Synth synth;
typedef jack_default_audio_sample_t sample_t;
const double PI = 3.14;
jack_client_t *client;
jack_port_t *output_port;
unsigned long sr;
int freq = 880;
int bpm;
jack_nframes_t tone_length, wave_length;
sample_t *wave;
long offset = 0;
int transport_aware = 0;
jack_transport_state_t transport_state;
void usage () {
fprintf (stderr, "\n"
"usage: jack_metro \n"
" [ --frequency OR -f frequency (in Hz) ]\n"
" [ --amplitude OR -A maximum amplitude (between 0 and 1) ]\n"
" [ --duration OR -D duration (in ms) ]\n"
" [ --attack OR -a attack (in percent of duration) ]\n"
" [ --decay OR -d decay (in percent of duration) ]\n"
" [ --name OR -n jack name for metronome client ]\n"
" [ --transport OR -t transport aware ]\n"
" --bpm OR -b beats per minute\n"
);
}
void
process_silence (jack_nframes_t nframes)
{
sample_t *buffer = (sample_t *) jack_port_get_buffer (output_port, nframes);
memset (buffer, 0, sizeof (jack_default_audio_sample_t) * nframes);
}
void
process_audio (jack_nframes_t nframes)
{
sample_t *buffer = (sample_t *) jack_port_get_buffer (output_port, nframes);
for(int i = 0; i < nframes; i++) {
buffer[i] = synth_render_sample(&synth) / 32767.0;
}
// jack_nframes_t frames_left = nframes;
// while (wave_length - offset < frames_left) {
// memcpy (buffer + (nframes - frames_left), wave + offset, sizeof (sample_t) * (wave_length - offset));
// frames_left -= wave_length - offset;
// offset = 0;
// }
// if (frames_left > 0) {
// memcpy (buffer + (nframes - frames_left), wave + offset, sizeof (sample_t) * frames_left);
// offset += frames_left;
// }
}
int
process (jack_nframes_t nframes, void *arg)
{
if (transport_aware) {
jack_position_t pos;
if (jack_transport_query (client, &pos)
!= JackTransportRolling) {
process_silence (nframes);
return 0;
}
offset = pos.frame % wave_length;
}
process_audio (nframes);
return 0;
}
int
sample_rate_change () {
printf("Sample rate has changed! Exiting...\n");
exit(-1);
}
static char *midi_note_names[12] = {
"C",
"C#",
"D",
"D#",
"E",
"F",
"F#",
"G",
"G#",
"A",
"A#",
"B",
};
const char *midi_note_name(int note) {
return midi_note_names[note % 12];
}
snd_seq_t *open_seq();
void midi_action(snd_seq_t *seq_handle);
snd_seq_t *open_seq() {
snd_seq_t *seq_handle;
int portid;
if (snd_seq_open(&seq_handle, "default", SND_SEQ_OPEN_INPUT, 0) < 0) {
fprintf(stderr, "Error opening ALSA sequencer.\n");
exit(1);
}
snd_seq_set_client_name(seq_handle, "Vampi Synth");
if ((portid = snd_seq_create_simple_port(seq_handle, "Cornhole",
SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE,
SND_SEQ_PORT_TYPE_APPLICATION)) < 0) {
fprintf(stderr, "Error creating sequencer port.\n");
exit(1);
}
return(seq_handle);
}
void midi_action(snd_seq_t *seq_handle) {
snd_seq_event_t *ev;
do {
snd_seq_event_input(seq_handle, &ev);
switch (ev->type) {
case SND_SEQ_EVENT_NOTEON:
printf("Note on %d (%s) %d\n", ev->data.note.note, midi_note_name(ev->data.note.note), ev->data.note.velocity);
synth_note_on(&synth, ev->data.note.note, ev->data.note.velocity);
break;
case SND_SEQ_EVENT_NOTEOFF:
printf("Note off %d\n", ev->data.note.note);
synth_note_off(&synth, ev->data.note.note, ev->data.note.velocity);
break;
}
snd_seq_free_event(ev);
} while (snd_seq_event_input_pending(seq_handle, 0) > 0);
}
int main(int argc, char **argv) {
sample_t scale;
int i, attack_length, decay_length;
double *amp;
double max_amp = 0.5;
int option_index;
int opt;
int got_bpm = 0;
int attack_percent = 1, decay_percent = 10, dur_arg = 100;
char *client_name = 0;
char *bpm_string = "bpm";
int verbose = 0;
jack_status_t status;
const char *options = "f:A:D:a:d:b:n:thv";
struct option long_options[] =
{
{"name", 1, 0, 'n'},
{"transport", 0, 0, 't'},
{"help", 0, 0, 'h'},
{"verbose", 0, 0, 'v'},
{0, 0, 0, 0}
};
while ((opt = getopt_long (argc, argv, options, long_options, &option_index)) != EOF) {
switch (opt) {
case 'n':
client_name = (char *) malloc (strlen (optarg) * sizeof (char));
strcpy (client_name, optarg);
break;
case 't':
transport_aware = 1;
break;
default:
fprintf (stderr, "unknown option %c\n", opt);
case 'h':
usage ();
return -1;
case 'v':
verbose = 1;
break;
}
}
/* Initial Jack setup, get sample rate */
if (!client_name) {
client_name = (char *) malloc (9 * sizeof (char));
strcpy (client_name, "metro");
}
if ((client = jack_client_open (client_name, JackNoStartServer, &status)) == 0) {
fprintf (stderr, "jack server not running?\n");
return 1;
}
jack_set_process_callback (client, process, 0);
output_port = jack_port_register (client, bpm_string, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
sr = jack_get_sample_rate (client);
synth_init(&synth);
synth.attack = 50;
synth.decay = 200;
synth.sustain = 60;
synth.release = 100;
/* setup wave table parameters */
if (jack_activate (client)) {
fprintf (stderr, "cannot activate client");
return 1;
}
snd_seq_t *seq_handle;
int npfd;
struct pollfd *pfd;
seq_handle = open_seq();
npfd = snd_seq_poll_descriptors_count(seq_handle, POLLIN);
pfd = (struct pollfd *)alloca(npfd * sizeof(struct pollfd));
snd_seq_poll_descriptors(seq_handle, pfd, npfd, POLLIN);
while (1) {
printf("poll\n");
if (poll(pfd, npfd, 100000) > 0) {
midi_action(seq_handle);
}
}
}

@ -0,0 +1,100 @@
#include <stdio.h>
#include "synth.h"
#include "config.h"
#include "tables.inc"
void synth_init(struct Synth *synth) {
}
uint8_t midi_notes[128];
void synth_note_on(struct Synth *synth, uint8_t note, uint8_t velocity) {
for(int i = 0; i < SYNTH_NUM_VOICES; i++) {
struct Voice *voice = synth->voices + i;
if(voice->env_state == None) {
voice->phase = voice->time = 0;
voice->freq = (uint32_t)(midi_note_freq_table[note & 0x7f] * 256);
midi_notes[note & 0x7f] = i;
voice->attack = synth->attack;
voice->decay = synth->decay;
voice->sustain = synth->sustain;
voice->release = synth->release;
voice->volume = velocity;
voice->env_state = Attack;
printf("Attack %d\n", synth->attack);
break;
}
}
}
void synth_note_off(struct Synth *synth, uint8_t note, uint8_t velocity) {
(void)velocity;
struct Voice *voice = synth->voices + midi_notes[note & 0x7f];
voice->time = 0;
voice->env_state = Release;
printf("Release %d\n", voice->release);
}
int16_t synth_render_sample(struct Synth *synth) {
int32_t smpl = 0;
for(int i = 0; i < SYNTH_NUM_VOICES; i++) {
struct Voice *v = synth->voices + i;
if(v->env_state != None) {
v->time++;
int32_t amplitude = 0; // calculate based on velocity and envelope
uint32_t ms_time = v->time * 1000 / SAMPLE_RATE;
switch(v->env_state) {
case Attack:
if(v->attack > 0)
amplitude = v->volume * ms_time / v->attack;
if(ms_time > v->attack) {
printf("Decay %d\n", v->decay);
v->env_state = Decay;
v->time = 0;
}
break;
case Decay:
if(v->decay > 0)
amplitude = (100 * v->volume * (v->decay - ms_time) + v->sustain * v->volume * ms_time) / v->decay / 100;
if(ms_time > v->decay) {
printf("Sustain %d\n", v->sustain);
v->env_state = Sustain;
v->time = 0;
}
break;
case Sustain:
amplitude = v->volume * v->sustain / 100;
break;
case Release:
amplitude = v->volume * (v->release - ms_time) * v->sustain / v->release / 100;
if(ms_time > v->release) {
v->time = 0;
v->freq = 0;
v->env_state = None;
printf("None\n");
}
break;
}
if(v->env_state != None && v->freq) {
v->phase += (1 << 8);
uint32_t freq_phase = (SAMPLE_RATE << 16) / v->freq;
while(v->phase >= freq_phase)
v->phase -= freq_phase;
int sine_phase = 256 * v->phase / freq_phase;
int sine_phase_next = (sine_phase + 1) & 0xff;
int sine_remainder = v->phase % freq_phase;
// if(v->env_state == Release) {
// printf("amplitude %d volume=%d time=%d ms_time=%d v->release=%d v->sustain=%d\n", amplitude, v->volume, v->time, ms_time, v->release, v->sustain);
// }
smpl += amplitude * sine_table_256[sine_phase] / 255;
}
if(smpl > 32767) smpl = 32767;
if(smpl < -32768) smpl = -32768;
}
}
return smpl & 0xffff;
}

@ -0,0 +1,38 @@
#ifndef SYNTH_H_
#define SYNTH_H_
#include <stdint.h>
#define SYNTH_NUM_VOICES 64
#define TUNING 440
struct Voice {
uint32_t phase;
uint32_t time;
uint16_t volume;
uint32_t freq;
// Envelope
enum {
None,
Attack,
Decay,
Sustain,
Release
} env_state;
uint16_t attack, decay, release; // in ms
uint16_t sustain; // percentage
};
struct Synth {
struct Voice voices[SYNTH_NUM_VOICES];
uint16_t attack, decay, sustain, release; // in ms
};
void synth_init(struct Synth *synth);
void synth_note_on(struct Synth *synth, uint8_t note, uint8_t velocity);
void synth_note_off(struct Synth *synth, uint8_t note, uint8_t velocity);
int16_t synth_render_sample(struct Synth *synth);
#endif /* SYNTH_H_ */

@ -0,0 +1,389 @@
static const int16_t sine_table_256[256] = {
0,
402,
804,
1205,
1606,
2005,
2404,
2801,
3196,
3590,
3981,
4370,
4756,
5139,
5519,
5896,
6270,
6639,
7005,
7366,
7723,
8075,
8423,
8765,
9102,
9433,
9759,
10079,
10393,
10701,
11002,
11297,
11585,
11865,
12139,
12405,
12664,
12915,
13159,
13394,
13622,
13841,
14052,
14255,
14449,
14634,
14810,
14977,
15136,
15285,
15425,
15556,
15678,
15790,
15892,
15985,
16068,
16142,
16206,
16260,
16304,
16339,
16363,
16378,
16383,
16378,
16363,
16339,
16304,
16260,
16206,
16142,
16068,
15985,
15892,
15790,
15678,
15556,
15425,
15285,
15136,
14977,
14810,
14634,
14449,
14255,
14052,
13841,
13622,
13394,
13159,
12915,
12664,
12405,
12139,
11865,
11585,
11297,
11002,
10701,
10393,
10079,
9759,
9433,
9102,
8765,
8423,
8075,
7723,
7366,
7005,
6639,
6270,
5896,
5519,
5139,
4756,
4370,
3981,
3590,
3196,
2801,
2404,
2005,
1606,
1205,
804,
402,
0,
-402,
-804,
-1205,
-1606,
-2005,
-2404,
-2801,
-3196,
-3590,
-3981,
-4370,
-4756,
-5139,
-5519,
-5896,
-6270,
-6639,
-7005,
-7366,
-7723,
-8075,
-8423,
-8765,
-9102,
-9433,
-9759,
-10079,
-10393,
-10701,
-11002,
-11297,
-11585,
-11865,
-12139,
-12405,
-12664,
-12915,
-13159,
-13394,
-13622,
-13841,
-14052,
-14255,
-14449,
-14634,
-14810,
-14977,
-15136,
-15285,
-15425,
-15556,
-15678,
-15790,
-15892,
-15985,
-16068,
-16142,
-16206,
-16260,
-16304,
-16339,
-16363,
-16378,
-16383,
-16378,
-16363,
-16339,
-16304,
-16260,
-16206,
-16142,
-16068,
-15985,
-15892,
-15790,
-15678,
-15556,
-15425,
-15285,
-15136,
-14977,
-14810,
-14634,
-14449,
-14255,
-14052,
-13841,
-13622,
-13394,
-13159,
-12915,
-12664,
-12405,
-12139,
-11865,
-11585,
-11297,
-11002,
-10701,
-10393,
-10079,
-9759,
-9433,
-9102,
-8765,
-8423,
-8075,
-7723,
-7366,
-7005,
-6639,
-6270,
-5896,
-5519,
-5139,
-4756,
-4370,
-3981,
-3590,
-3196,
-2801,
-2404,
-2005,
-1606,
-1205,
-804,
};
// http://www.richardbrice.net/midi_notes.htm
static const float midi_note_freq_table[128] = {
8.176,
8.662,
9.177,
9.723,
10.301,
10.913,
11.562,
12.250,
12.978,
13.750,
14.568,
15.434,
16.352,
17.324,
18.354,
19.445,
20.601,
21.826,
23.124,
24.499,
25.956,
27.500, // Lowest note on piano
29.135,
30.867,
32.703,
34.648,
36.708,
38.890,
41.203,
43.653,
46.249,
48.999,
51.913,
55.000,
58.270,
61.735,
65.406,
69.295,
73.416,
77.781,
82.406,
87.307,
92.499,
97.998,
103.82,
110.00,
116.54,
123.47,
130.81,
138.59,
146.83,
155.56,
164.81,
174.61,
184.99,
195.99,
207.65,
220.00,
233.08,
246.94,
261.63, // Middle-C
277.18,
293.66,
311.13,
329.63,
349.23,
369.99,
391.99,
415.31,
440.00,
466.16,
489.88,
523.25,
554.37,
587.33,
622.25,
659.26,
698.46,
739.99,
783.99,
830.61,
880.00,
932.32,
987.77,
1046.5,
1108.7,
1174.7,
1244.5,
1318.5,
1396.9,
1480.0,
1568.0,
1661.2,
1760.0,
1864.7,
1975.5,
2093.0,
2217.5,
2349.3,
2489.0,
2637.0,
2793.8,
2960.0,
3136.0,
3322.4,
3520.0,
3729.3,
3951.1,
4186.0, // Highest note on piano
4434.9,
4698.6,
4978.0,
5274.0,
5587.7,
5919.9,
6271.9,
6644.9,
7040.0,
7458.6,
7902.1,
8372.0,
8869.8,
9397.3,
9956.1,
10548.1,
11175.3,
11839.8,
12543.9,
};
Loading…
Cancel
Save