Guest User

Untitled

a guest
Dec 16th, 2018
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.33 KB | None | 0 0
  1. /* protosynth
  2. *
  3. * Throughout the source code, "frequency" refers to a Hz value,
  4. * and "pitch" refers to a numeric musical note value with 0 representing C0, 12 for C1, etc..
  5. *
  6. * compiled with:
  7. * gcc -Wall protosynth.c -o protosynth `sdl2-config --cflags --libs` -lm
  8. */
  9.  
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <math.h>
  13. #include "SDL.h"
  14.  
  15. const double ChromaticRatio = 1.059463094359295264562;
  16. const double Tao = 6.283185307179586476925;
  17.  
  18. Uint32 sampleRate = 48000;
  19. Uint32 frameRate = 60;
  20. Uint32 floatStreamLength = 1024;// must be a power of two, decrease to allow for a lower syncCompensationFactor to allow for lower latency, increase to reduce risk of underrun
  21. Uint32 samplesPerFrame; // = sampleRate/frameRate;
  22. Uint32 msPerFrame; // = 1000/frameRate;
  23. double practicallySilent = 0.001;
  24.  
  25. Uint32 audioBufferLength = 48000;// must be a multiple of samplesPerFrame (auto adjusted upwards if not)
  26. float *audioBuffer;
  27.  
  28. SDL_atomic_t audioCallbackLeftOff;
  29. Sint32 audioMainLeftOff;
  30. Uint8 audioMainAccumulator;
  31.  
  32. SDL_AudioDeviceID AudioDevice;
  33. SDL_AudioSpec audioSpec;
  34.  
  35. SDL_Event event;
  36. SDL_bool running = SDL_TRUE;
  37.  
  38.  
  39. typedef struct {
  40. float *waveform;
  41. Uint32 waveformLength;
  42. double volume; // multiplied
  43. double pan; // 0 to 1: all the way left to all the way right
  44. double frequency; // Hz
  45. double phase; // 0 to 1
  46. } voice;
  47.  
  48. /* _
  49. | |
  50. ___ _ __ ___ __ _| | __
  51. / __| '_ / _ / _` | |/ /
  52. __ |_) | __/ (_| | <
  53. |___/ .__/ ___|__,_|_|_
  54. | |
  55. |_|
  56. */
  57. void speak(voice *v) {
  58. float sample;
  59. Uint32 sourceIndex;
  60. double phaseIncrement = v->frequency/sampleRate;
  61. Uint32 i;
  62. if (v->volume > practicallySilent) {
  63. for (i=0; (i+1)<samplesPerFrame; i+=2) {
  64.  
  65. v->phase += phaseIncrement;
  66. if (v->phase > 1) v->phase -= 1;
  67.  
  68. sourceIndex = v->phase*v->waveformLength;
  69. sample = v->waveform[sourceIndex]*v->volume;
  70.  
  71. audioBuffer[audioMainLeftOff+i] += sample*(1-v->pan); //left channel
  72. audioBuffer[audioMainLeftOff+i+1] += sample*v->pan; //right channel
  73. }
  74. }
  75. else {
  76. for (i=0; i<samplesPerFrame; i+=1)
  77. audioBuffer[audioMainLeftOff+i] = 0;
  78. }
  79. audioMainAccumulator++;
  80. }
  81.  
  82. double getFrequency(double pitch) {
  83. return pow(ChromaticRatio, pitch-57)*440;
  84. }
  85. int getWaveformLength(double pitch) {
  86. return sampleRate / getFrequency(pitch)+0.5f;
  87. }
  88.  
  89. void buildSineWave(float *data, Uint32 length) {
  90. Uint32 i;
  91. for (i=0; i < length; i++)
  92. data[i] = sin( i*(Tao/length) );
  93. }
  94.  
  95. void logSpec(SDL_AudioSpec *as) {
  96. printf(
  97. " freq______%5dn"
  98. " format____%5dn"
  99. " channels__%5dn"
  100. " silence___%5dn"
  101. " samples___%5dn"
  102. " size______%5dnn",
  103. (int) as->freq,
  104. (int) as->format,
  105. (int) as->channels,
  106. (int) as->silence,
  107. (int) as->samples,
  108. (int) as->size
  109. );
  110. }
  111.  
  112. void logVoice(voice *v) {
  113. printf(
  114. " waveformLength__%dn"
  115. " volume__________%fn"
  116. " pan_____________%fn"
  117. " frequency_______%fn"
  118. " phase___________%fn",
  119. v->waveformLength,
  120. v->volume,
  121. v->pan,
  122. v->frequency,
  123. v->phase
  124. );
  125. }
  126.  
  127. void logWavedata(float *floatStream, Uint32 floatStreamLength, Uint32 increment) {
  128. printf("nnwaveform data:nn");
  129. Uint32 i=0;
  130. for (i=0; i<floatStreamLength; i+=increment)
  131. printf("%4d:%2.16fn", i, floatStream[i]);
  132. printf("nn");
  133. }
  134.  
  135. /* _ _ _____ _ _ _ _
  136. | (_) / ____| | | | | | |
  137. __ _ _ _ __| |_ ___ | | __ _| | | |__ __ _ ___| | __
  138. / _` | | | |/ _` | |/ _ | | / _` | | | '_ / _` |/ __| |/ /
  139. | (_| | |_| | (_| | | (_) | |___| (_| | | | |_) | (_| | (__| <
  140. __,_|__,_|__,_|_|___/ _______,_|_|_|_.__/ __,_|___|_|_
  141. */
  142. void audioCallback(void *unused, Uint8 *byteStream, int byteStreamLength) {
  143. float* floatStream = (float*) byteStream;
  144.  
  145. Sint32 localAudioCallbackLeftOff = SDL_AtomicGet(&audioCallbackLeftOff);
  146.  
  147. Uint32 i;
  148. for (i=0; i<floatStreamLength; i++) {
  149.  
  150. floatStream[i] = audioBuffer[localAudioCallbackLeftOff];
  151.  
  152. localAudioCallbackLeftOff++;
  153. if ( localAudioCallbackLeftOff == audioBufferLength )
  154. localAudioCallbackLeftOff = 0;
  155. }
  156. //printf("localAudioCallbackLeftOff__%5dn", localAudioCallbackLeftOff);
  157.  
  158. SDL_AtomicSet(&audioCallbackLeftOff, localAudioCallbackLeftOff);
  159. }
  160.  
  161. /*_ _ _
  162. (_) (_) |
  163. _ _ __ _| |_
  164. | | '_ | | __|
  165. | | | | | | |_
  166. |_|_| |_|_|__|
  167. */
  168. int init() {
  169. SDL_Init(SDL_INIT_AUDIO | SDL_INIT_TIMER);
  170.  
  171. SDL_AudioSpec want;
  172.  
  173. SDL_zero(want);// btw, I have no idea what this is...
  174.  
  175. want.freq = sampleRate;
  176. want.format = AUDIO_F32;
  177. want.channels = 2;
  178. want.samples = floatStreamLength;
  179. want.callback = audioCallback;
  180.  
  181. AudioDevice = SDL_OpenAudioDevice(NULL, 0, &want, &audioSpec, SDL_AUDIO_ALLOW_FORMAT_CHANGE);
  182.  
  183. if (AudioDevice == 0) {
  184. printf("nFailed to open audio: %sn", SDL_GetError());
  185. return 1;
  186. }
  187.  
  188. printf("want:n");
  189. logSpec(&want);
  190. printf("audioSpec:n");
  191. logSpec(&audioSpec);
  192.  
  193. if (audioSpec.format != want.format) {
  194. printf("nCouldn't get Float32 audio format.n");
  195. return 2;
  196. }
  197.  
  198. sampleRate = audioSpec.freq;
  199. floatStreamLength = audioSpec.size/4;
  200. samplesPerFrame = sampleRate/frameRate;
  201. msPerFrame = 1000/frameRate;
  202. audioMainLeftOff = samplesPerFrame*8;
  203. SDL_AtomicSet(&audioCallbackLeftOff, 0);
  204.  
  205. if (audioBufferLength % samplesPerFrame)
  206. audioBufferLength += samplesPerFrame-(audioBufferLength % samplesPerFrame);
  207. audioBuffer = malloc( sizeof(float)*audioBufferLength );
  208.  
  209. return 0;
  210. }
  211. int onExit() {
  212. SDL_CloseAudioDevice(AudioDevice);
  213. //free(audioBuffer);//not necessary?
  214. SDL_Quit();
  215. return 0;
  216. }
  217.  
  218. /* _
  219. (_)
  220. _ __ ___ __ _ _ _ __
  221. | '_ ` _ / _` | | '_
  222. | | | | | | (_| | | | | |
  223. |_| |_| |_|__,_|_|_| |_|
  224. */
  225. int main(int argc, char *argv[]) {
  226.  
  227. float syncCompensationFactor = 0.0016;// decrease to reduce risk of collision, increase to lower latency
  228. Sint32 mainAudioLead;
  229. Uint32 i;
  230.  
  231. voice testVoiceA;
  232. voice testVoiceB;
  233. voice testVoiceC;
  234. testVoiceA.volume = 1;
  235. testVoiceB.volume = 1;
  236. testVoiceC.volume = 1;
  237. testVoiceA.pan = 0.5;
  238. testVoiceB.pan = 0;
  239. testVoiceC.pan = 1;
  240. testVoiceA.phase = 0;
  241. testVoiceB.phase = 0;
  242. testVoiceC.phase = 0;
  243. testVoiceA.frequency = getFrequency(45);// A3
  244. testVoiceB.frequency = getFrequency(49);// C#4
  245. testVoiceC.frequency = getFrequency(52);// E4
  246. Uint16 C0waveformLength = getWaveformLength(0);
  247. testVoiceA.waveformLength = C0waveformLength;
  248. testVoiceB.waveformLength = C0waveformLength;
  249. testVoiceC.waveformLength = C0waveformLength;
  250. float sineWave[C0waveformLength];
  251. buildSineWave(sineWave, C0waveformLength);
  252. testVoiceA.waveform = sineWave;
  253. testVoiceB.waveform = sineWave;
  254. testVoiceC.waveform = sineWave;
  255.  
  256. //logVoice(&testVoiceA);
  257. //logWavedata(testVoiceA.waveform, testVoiceA.waveformLength, 10);
  258.  
  259. if ( init() ) return 1;
  260.  
  261. SDL_Delay(42);// let the tubes warm up
  262.  
  263. SDL_PauseAudioDevice(AudioDevice, 0);// unpause audio.
  264.  
  265. while (running) {
  266. while( SDL_PollEvent( &event ) != 0 ) {
  267. if( event.type == SDL_QUIT ) {
  268. running = SDL_FALSE;
  269. }
  270. }
  271. for (i=0; i<samplesPerFrame; i++) audioBuffer[audioMainLeftOff+i] = 0;
  272.  
  273. //printf("audioMainLeftOff___________%5dn", audioMainLeftOff);
  274.  
  275. speak(&testVoiceA);
  276. speak(&testVoiceB);
  277. speak(&testVoiceC);
  278.  
  279. if (audioMainAccumulator > 1) {
  280. for (i=0; i<samplesPerFrame; i++) {
  281. audioBuffer[audioMainLeftOff+i] /= audioMainAccumulator;
  282. }
  283. }
  284. audioMainAccumulator = 0;
  285.  
  286. audioMainLeftOff += samplesPerFrame;
  287. if (audioMainLeftOff == audioBufferLength) audioMainLeftOff = 0;
  288.  
  289. mainAudioLead = audioMainLeftOff - SDL_AtomicGet(&audioCallbackLeftOff);
  290. if (mainAudioLead < 0) mainAudioLead += audioBufferLength;
  291. //printf("mainAudioLead:%5dn", mainAudioLead);
  292. if (mainAudioLead < floatStreamLength) printf("An audio collision may have occured!n");
  293. SDL_Delay( mainAudioLead*syncCompensationFactor );
  294. }
  295. onExit();
  296. return 0;
  297. }
  298.  
  299. {
  300. <from SDL_TimerInit>
  301. Memcheck:Leak
  302. match-leak-kinds: possible
  303. fun:calloc
  304. fun:allocate_dtv
  305. fun:_dl_allocate_tls
  306. fun:pthread_create@@GLIBC_2.2.5
  307. fun:SDL_SYS_CreateThread
  308. fun:SDL_CreateThread
  309. fun:SDL_TimerInit
  310. fun:SDL_InitSubSystem
  311. fun:init
  312. fun:main
  313. }
  314. {
  315. <from SDL_AudioInit>
  316. Memcheck:Leak
  317. match-leak-kinds: possible
  318. fun:calloc
  319. fun:allocate_dtv
  320. fun:_dl_allocate_tls
  321. fun:pthread_create@@GLIBC_2.2.5
  322. fun:pa_thread_new
  323. fun:pa_threaded_mainloop_start
  324. fun:pa_simple_new
  325. fun:PULSEAUDIO_Init
  326. fun:SDL_AudioInit
  327. fun:SDL_InitSubSystem
  328. fun:init
  329. fun:main
  330. }
  331.  
  332. #include <SDL/SDL.h>
  333.  
  334. #include <h-char-sequence> new-line
  335.  
  336. #include "q-char-sequence" new-line
  337.  
  338. #include <h-char-sequence> new-line
  339.  
  340. #include pp-tokens new-line
  341.  
  342. const double Tao = 6.283185307179586476925;
  343.  
  344. const double TAO = 2 * M_PI;
  345.  
  346. audioBuffer = malloc( sizeof(float)*audioBufferLength );
  347. // free(audioBuffer); //not necessary?
  348.  
  349. uint32_t sampleRate = 48000;
  350.  
  351. for (uint32_t i = 0; (i+1) < samplesPerFrame; i += 2)
  352.  
  353. typedef struct
  354. {
  355. float *waveform;
  356. Uint32 waveformLength;
  357. double volume; // multiplied
  358. double pan; // 0 to 1: all the way left to all the way right
  359. double frequency; // Hz
  360. double phase; // 0 to 1
  361. } Voice;
  362.  
  363. int init(void)
  364.  
  365. int main(int argc, char *argv[])
  366.  
  367. int main(void)
  368.  
  369. printf("nnwaveform data:nn");
  370.  
  371. puts("Waveform data: ");
  372.  
  373. /* _ _ _____ _ _ _ _
  374. | (_) / ____| | | | | | |
  375. __ _ _ _ __| |_ ___ | | __ _| | | |__ __ _ ___| | __
  376. / _` | | | |/ _` | |/ _ | | / _` | | | '_ / _` |/ __| |/ /
  377. | (_| | |_| | (_| | | (_) | |___| (_| | | | |_) | (_| | (__| <
  378. __,_|__,_|__,_|_|___/ _______,_|_|_|_.__/ __,_|___|_|_
  379. */
  380.  
  381. /**
  382. * @fn static void json_fillToken(JsonToken *token, JsonType type, int start, int end)
  383. * @brief Fills token type and boundaries.
  384. * @param token
  385. * @param type
  386. * @param start
  387. * @param end
  388. */
  389. static void json_fillToken(JsonToken *token, JsonType type, int start, int end)
  390. {
  391. token->type = type;
  392. token->start = start;
  393. token->end = end;
  394. token->size = 0;
  395. }
  396.  
  397. //logVoice(&testVoiceA);
  398. //logWavedata(testVoiceA.waveform, testVoiceA.waveformLength, 10);
  399.  
  400. int onExit() {
  401. SDL_CloseAudioDevice(AudioDevice);
  402. //free(audioBuffer);//not necessary?
  403. SDL_Quit();
  404. return 0;
  405. }
  406.  
  407. int main(void)
  408. {
  409. ...
  410. atexit(cleanup);
  411. return 0;
  412. }
Add Comment
Please, Sign In to add comment