Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
381 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
CC=gcc | ||
CFLAGS = -O3 -g -Wall -pedantic | ||
LDFLAGS = -llo -lsndfile -lsamplerate -ljack | ||
|
||
all: dirt | ||
|
||
clean : | ||
rm -f *.o *~ dirt | ||
|
||
dirt: dirt.o jack.o audio.o file.o Makefile | ||
$(CC) dirt.o jack.o audio.o file.o $(CFLAGS) $(LDFLAGS) -o dirt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
|
||
extern int audio_callback(int samples, float *buffer) { | ||
int i; | ||
for (i=0; i < samples; ++i) { | ||
buffer[0] = 0; | ||
} | ||
return(0); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
|
||
extern int audio_callback(int samples, float *buffer); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#include <stdio.h> | ||
|
||
#include <unistd.h> | ||
|
||
#include "jack.h" | ||
#include "audio.h" | ||
|
||
int main (int argc, char **argv) { | ||
int samplerate = jack_start(audio_callback); | ||
|
||
sleep(-1); | ||
return(0); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
#include <sndfile.h> | ||
#include <samplerate.h> | ||
#include <string.h> | ||
#include <dirent.h> | ||
#include <stdlib.h> | ||
|
||
#include "file.h" | ||
|
||
t_sample *samples[MAXSAMPLES]; | ||
int sample_count = 0; | ||
|
||
|
||
t_sample *find_sample (char *samplename) { | ||
int c; | ||
t_sample *sample = NULL; | ||
|
||
for(c = 0; c < sample_count; ++c) { | ||
if(strcmp(samples[c]->name, samplename) == 0) { | ||
sample = samples[c]; | ||
break; | ||
} | ||
} | ||
return(sample); | ||
} | ||
|
||
int wav_filter (const struct dirent *d) { | ||
if (strlen(d->d_name) > 4) { | ||
printf("%s\n", d->d_name + strlen(d->d_name) - 4); | ||
return(strcmp(d->d_name + strlen(d->d_name) - 4, ".wav") == 0); | ||
} | ||
return(0); | ||
} | ||
|
||
void fix_samplerate (t_sample *sample, int samplerate) { | ||
SRC_DATA data; | ||
int max_output_frames; | ||
int channels = sample->info->channels; | ||
|
||
data.src_ratio = sample->info->samplerate / samplerate; | ||
|
||
max_output_frames = sample->info->frames * data.src_ratio + 32; | ||
|
||
data.data_in = sample->frames; | ||
data.input_frames = sample->info->frames; | ||
|
||
data.data_out = (float *) malloc(sizeof(float) | ||
* max_output_frames | ||
* channels | ||
); | ||
data.output_frames = max_output_frames; | ||
|
||
src_simple(&data, SRC_SINC_BEST_QUALITY, channels); | ||
|
||
sample->frames = data.data_out; | ||
sample->info->samplerate = samplerate; | ||
sample->info->frames = data.output_frames_gen; | ||
} | ||
|
||
t_sample *get_sample(char *samplename, int samplerate) { | ||
SNDFILE *sndfile; | ||
char path[MAXPATHSIZE]; | ||
char error[62]; | ||
t_sample *sample; | ||
sf_count_t count; | ||
float *frames; | ||
SF_INFO *info; | ||
char set[MAXPATHSIZE]; | ||
int set_n = 0; | ||
struct dirent **namelist; | ||
|
||
sample = find_sample(samplename); | ||
|
||
if (sample == NULL) { | ||
/* load it from disk */ | ||
if (sscanf(samplename, "%[a-z0-9A-Z]/%d", set, &set_n)) { | ||
int n; | ||
snprintf(path, MAXPATHSIZE -1, "%s/%s", SAMPLEROOT, set); | ||
n = scandir(path, &namelist, wav_filter, alphasort); | ||
if (n > 0) { | ||
snprintf(path, MAXPATHSIZE -1, | ||
"%s/%s/%s", SAMPLEROOT, set, namelist[set_n % n]->d_name); | ||
while (n--) { | ||
free(namelist[n]); | ||
} | ||
free(namelist); | ||
} | ||
else { | ||
path[0] = '\0'; | ||
} | ||
} | ||
else { | ||
snprintf(path, MAXPATHSIZE -1, "%s/%s", SAMPLEROOT, samplename); | ||
} | ||
info = (SF_INFO *) calloc(1, sizeof(SF_INFO)); | ||
|
||
if ((sndfile = (SNDFILE *) sf_open(path, SFM_READ, info)) == NULL) { | ||
free(info); | ||
} | ||
else { | ||
frames = (float *) malloc(sizeof(float) * info->frames); | ||
snprintf(error, (size_t) 61, "hm: %d\n", sf_error(sndfile)); | ||
perror(error); | ||
count = sf_read_float(sndfile, frames, info->frames); | ||
snprintf(error, (size_t) 61, "hmm: %d vs %d %d\n", (int) count, (int) info->frames, sf_error(sndfile)); | ||
perror(error); | ||
|
||
if (count == info->frames) { | ||
sample = (t_sample *) calloc(1, sizeof(t_sample)); | ||
strncpy(sample->name, samplename, MAXPATHSIZE - 1); | ||
sample->info = info; | ||
sample->frames = frames; | ||
samples[sample_count++] = sample; | ||
} | ||
else { | ||
snprintf(error, (size_t) 61, "didn't get the right number of frames: %d vs %d %d\n", (int) count, (int) info->frames, sf_error(sndfile)); | ||
perror(error); | ||
free(info); | ||
free(frames); | ||
} | ||
} | ||
fix_samplerate(sample, samplerate); | ||
} | ||
|
||
return(sample); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
|
||
#define MAXSAMPLES 1024 | ||
#define MAXFILES 4096 | ||
#define MAXPATHSIZE 256 | ||
|
||
#define SAMPLEROOT "./" | ||
|
||
typedef struct { | ||
char name[MAXPATHSIZE]; | ||
SF_INFO *info; | ||
float *frames; | ||
} t_sample; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
#include <stdio.h> | ||
#include <errno.h> | ||
#include <unistd.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
|
||
#include <jack/jack.h> | ||
|
||
#include "jack.h" | ||
|
||
jack_port_t *output_port; | ||
jack_client_t *client; | ||
|
||
int process(jack_nframes_t nframes, void *arg) { | ||
jack_default_audio_sample_t *out; | ||
t_callback callback = (t_callback) arg; | ||
|
||
out = jack_port_get_buffer(output_port, nframes); | ||
callback(nframes, out); | ||
|
||
return 0; | ||
} | ||
|
||
void jack_shutdown(void *arg) { | ||
exit(1); | ||
} | ||
|
||
extern int jack_start(t_callback callback) { | ||
const char **ports; | ||
const char *client_name = "dirt"; | ||
const char *server_name = NULL; | ||
jack_options_t options = JackNullOption; | ||
jack_status_t status; | ||
|
||
/* open a client connection to the JACK server */ | ||
|
||
client = jack_client_open(client_name, options, &status, server_name); | ||
if (client == NULL) { | ||
fprintf(stderr, "jack_client_open() failed, " | ||
"status = 0x%2.0x\n", status); | ||
if (status & JackServerFailed) { | ||
fprintf(stderr, "Unable to connect to JACK server\n"); | ||
} | ||
exit(1); | ||
} | ||
if (status & JackServerStarted) { | ||
fprintf(stderr, "JACK server started\n"); | ||
} | ||
if (status & JackNameNotUnique) { | ||
client_name = jack_get_client_name(client); | ||
fprintf(stderr, "unique name `%s' assigned\n", client_name); | ||
} | ||
|
||
jack_set_process_callback(client, process, callback); | ||
|
||
jack_on_shutdown(client, jack_shutdown, 0); | ||
|
||
printf("engine sample rate: %" PRIu32 "\n", | ||
jack_get_sample_rate(client)); | ||
|
||
output_port = jack_port_register(client, "output", | ||
JACK_DEFAULT_AUDIO_TYPE, | ||
JackPortIsOutput, 0); | ||
|
||
if (output_port == NULL) { | ||
fprintf(stderr, "no more JACK ports available\n"); | ||
exit(1); | ||
} | ||
|
||
if (jack_activate(client)) { | ||
fprintf(stderr, "cannot activate client"); | ||
exit(1); | ||
} | ||
|
||
ports = jack_get_ports(client, NULL, NULL, | ||
JackPortIsPhysical|JackPortIsInput); | ||
if (ports == NULL) { | ||
fprintf(stderr, "no physical playback ports\n"); | ||
exit(1); | ||
} | ||
|
||
if (jack_connect(client, jack_port_name(output_port), ports[0])) { | ||
fprintf(stderr, "cannot connect output ports\n"); | ||
} | ||
|
||
free(ports); | ||
|
||
return(jack_get_sample_rate(client)); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
|
||
|
||
typedef int (*t_callback)(int, float *); | ||
extern int jack_start(t_callback callback); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <unistd.h> | ||
#include <string.h> | ||
#include <lo/lo.h> | ||
|
||
#include "server.h" | ||
|
||
void error(int num, const char *m, const char *path); | ||
|
||
int trigger_handler(const char *path, const char *types, lo_arg **argv, | ||
int argc, void *data, void *user_data); | ||
|
||
int generic_handler(const char *path, const char *types, lo_arg **argv, | ||
int argc, void *data, void *user_data); | ||
|
||
/**/ | ||
|
||
extern int server_init(void) { | ||
lo_server_thread st = lo_server_thread_new("7771", error); | ||
|
||
#ifdef DEBUG | ||
lo_server_thread_add_method(st, NULL, NULL, generic_handler, NULL); | ||
#endif | ||
|
||
lo_server_thread_add_method(st, "/trigger", "sfffffsfffssffffff", | ||
trigger_handler, | ||
NULL | ||
); | ||
lo_server_thread_start(st); | ||
|
||
return(1); | ||
} | ||
|
||
/**/ | ||
|
||
void error(int num, const char *msg, const char *path) { | ||
printf("liblo server error %d in path %s: %s\n", num, path, msg); | ||
} | ||
|
||
/**/ | ||
|
||
int generic_handler(const char *path, const char *types, lo_arg **argv, | ||
int argc, void *data, void *user_data) | ||
{ | ||
int i; | ||
|
||
printf("path: <%s>\n", path); | ||
for (i=0; i<argc; i++) { | ||
printf("arg %d '%c' ", i, types[i]); | ||
lo_arg_pp(types[i], argv[i]); | ||
printf("\n"); | ||
} | ||
printf("\n"); | ||
|
||
return 1; | ||
} | ||
|
||
/**/ | ||
|
||
int trigger_handler(const char *path, const char *types, lo_arg **argv, | ||
int argc, void *data, void *user_data) { | ||
|
||
lo_timetag ts = lo_message_get_timestamp(data); | ||
|
||
char *sample_name = strdup((char *) argv[0]); | ||
float speed = argv[1]->f; | ||
float shape = argv[2]->f; | ||
float pan = argv[3]->f; | ||
float pan_to = argv[4]->f; | ||
float volume = argv[5]->f; | ||
char *envelope_name = strdup((char *) argv[6]); | ||
float anafeel_strength = argv[7]->f; | ||
float anafeel_frequency = argv[8]->f; | ||
float accellerate = argv[9]->f; | ||
char *vowel_s = (char *) argv[10]; | ||
char *scale_name = strdup((char *) argv[11]); | ||
float loops = argv[12]->f; | ||
float duration = argv[13]->f; | ||
float delay = argv[14]->f; | ||
float delay2 = argv[15]->f; | ||
float cutoff = argv[16]->f; | ||
float resonance = argv[17]->f; | ||
|
||
int vowel = -1; | ||
switch(vowel_s[0]) { | ||
case 'a': case 'A': vowel = 0; break; | ||
case 'e': case 'E': vowel = 1; break; | ||
case 'i': case 'I': vowel = 2; break; | ||
case 'o': case 'O': vowel = 3; break; | ||
case 'u': case 'U': vowel = 4; break; | ||
} | ||
|
||
audio_trigger(ts, | ||
sample_name, | ||
speed, | ||
shape, | ||
pan, | ||
pan_to, | ||
volume, | ||
envelope_name, | ||
anafeel_strength, | ||
anafeel_frequency, | ||
accellerate, | ||
vowel, | ||
scale_name, | ||
loops, | ||
duration, | ||
delay, | ||
delay2, | ||
cutoff, | ||
resonance | ||
); | ||
return 0; | ||
} | ||
|