-
Notifications
You must be signed in to change notification settings - Fork 0
/
oscillator.c
146 lines (120 loc) · 4 KB
/
oscillator.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#include "oscillator.h"
#include "synth.h"
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#define M_PI 3.14159265358979323846264338327
#define TWO_PI (2.0 * M_PI)
static void* oscillatorWork(void* arg){
oscillator* osc = (oscillator*) arg;
int currType;
int currFreq;
pthread_mutex_lock(&(osc->lock));
while(!osc->exit){
//Wait for synth to empty buffer
while(osc->done && !osc->exit){
pthread_cond_wait(&(osc->cond), &(osc->lock));
}
if (osc->exit){
break;
}
currType = osc->type;
currFreq = osc->freq;
pthread_mutex_unlock(&(osc->lock));
int sync = osc->sync;
int last;
int sampPerPeriod = 0;
int mod = 0;
if(currFreq == 0){
currType = -1;
}else {
sampPerPeriod = RATE / currFreq;
mod = sampPerPeriod / 2;
}
/* Fill buffer with stuff */
switch(currType){
case OSC_TYPE_SINE:;
double cost = TWO_PI * currFreq / (double)RATE;
for (int i = 0 ; i < BUFFERSIZE ; i++) {
last = (i + sync);
osc->buffer[i] = (int16_t)(INT16_MAX * sin(last * cost));
}
osc->sync = (last + 1);
break;
case OSC_TYPE_SAW:
for (int i = 0 ; i < BUFFERSIZE ; i++) {
last = (i + sync);
int inc = last % sampPerPeriod;
osc->buffer[i] = INT16_MIN + ((2 * inc * INT16_MAX) / sampPerPeriod);
}
osc->sync = (last + 1) % sampPerPeriod;
break;
case OSC_TYPE_SQUARE:
for (int i = 0 ; i < BUFFERSIZE ; i++) {
last = (i + sync);
osc->buffer[i] = ((last % sampPerPeriod) <= mod) ? (INT16_MAX - 100) : (INT16_MIN + 100);
}
osc->sync = (last + 1) % sampPerPeriod;
break;
case OSC_TYPE_TRIANGLE:
for (int i = 0 ; i < BUFFERSIZE ; i++) {
last = (i + sync);
int inc = last % sampPerPeriod;
osc->buffer[i] = INT16_MIN + abs(2 * (((2 * inc * INT16_MAX) / sampPerPeriod) - INT16_MAX));
}
osc->sync = (last + 1) % sampPerPeriod;
break;
default:
for (int i = 0 ; i < BUFFERSIZE ; i++) {
osc->buffer[i] = 0;
}
}
pthread_mutex_lock(&(osc->lock));
osc->done = 1;
pthread_cond_signal(&(osc->cond));
}
pthread_mutex_unlock(&(osc->lock));
return NULL;
}
oscillator* createOsc(int type, int freq){
//Allocate memory
oscillator* osc = malloc(sizeof(oscillator));
//Error check
if (osc == NULL){
perror("allocating memory for oscillator");
exit(-1);
}
//Allocate memory for buffer
osc->buffer = malloc(sizeof(int16_t) * BUFFERSIZE);
//Error check
if (osc->buffer == NULL){
perror("allocating memory for oscillator buffer");
exit(-1);
}
//Init values
osc->freq = freq;
osc->type = type;
osc->done = 0;
osc->sync = 0;
pthread_mutex_init(&(osc->lock), NULL);
//Start oscillator
pthread_create(&(osc->thread), NULL, &oscillatorWork, osc);
return osc;
}
void killThread(oscillator* osc){
pthread_mutex_lock(&(osc->lock));
osc->exit = 1;
pthread_cond_signal(&(osc->cond));
pthread_mutex_unlock(&(osc->lock));
pthread_join(osc->thread, NULL);
}
void setFreq(oscillator* osc, int freq){
pthread_mutex_lock(&(osc->lock));
osc->freq = freq;
pthread_mutex_unlock(&(osc->lock));
}
void setType(oscillator* osc, int type){
pthread_mutex_lock(&(osc->lock));
osc->type = type;
pthread_mutex_unlock(&(osc->lock));
}