Created
November 14, 2014 15:48
-
-
Save yousry/82e81efb50e8027c7b8f to your computer and use it in GitHub Desktop.
Source code for: "Adding subliminal stimuli in real-time to audio recordings" (http://www.yousry.de/adding-subliminal-stimuli-in-real-time-to-audio-recordingssprachmodul-v2-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
#include <stdlib.h> | |
#include <stdio.h> | |
#include <wchar.h> | |
#include <locale.h> | |
#include <stdbool.h> | |
#include <math.h> | |
#include "simpleAudio.h" | |
int main(int argc, char** argv) | |
{ | |
wprintf(L"Simple Audio Demo\n"); | |
bool sadInitOk = sad_initPulseAudio(); | |
if(argc != 2) { | |
wprintf(L"Usage: audioDemo Ogg-file\n"); | |
exit(1); | |
} | |
char* audiofile = argv[1]; | |
t_sad_stream *mStream = sad_getOggStream(audiofile); | |
const float fortyHZ = (float)mStream->rate / 40.0f; | |
int volN = 25; | |
float vol[volN]; | |
float *volP = vol; | |
__block int atLeast = 0; | |
const float minDuration = 50000; | |
// code injection into the stream worker. In this case pa | |
sad_callbackInjector =^(pa_stream *s, size_t length, void *userdata) | |
{ | |
t_sad_stream* streamData = (t_sad_stream*) userdata; | |
size_t remainingLength = MIN(length, streamData->size - streamData->seek); | |
// short range [-32767,+32767] | |
short *audioValues = (short*)mStream->data; | |
const size_t seekStart = streamData->seek / sizeof(short); | |
const size_t seekEnd = seekStart + remainingLength / sizeof(short); | |
for(size_t i = seekStart; i < seekEnd; i++) { | |
const int lId =i; | |
const int rId =i + 1; | |
float leftChannel = (float)audioValues[lId] / 32767.0f; | |
float rightChannel = (float)audioValues[rId] / 32767.0f; | |
volP[i % volN] = leftChannel+ rightChannel; | |
const float baseA = fmod((float)i, fortyHZ * 2.0f ) / ( fortyHZ * 2.0f); | |
const float baseB = fmod((float)i, (fortyHZ + 1.45f) * 2.0f ) / ( ( fortyHZ + 1.45f ) * 2.0f); | |
const float baseC = fmod((float)i, (fortyHZ + 2.0f ) * 2.0f ) / ( ( fortyHZ + 2.0f ) * 2.0f); | |
float v = 0; | |
// improve the prediction quality with a delay/lookahead | |
const int lookahead = MIN(volN, remainingLength); | |
for(int j = 1; j < lookahead; j++) { | |
v += fabsf(fmaxf(volP[j], volP[j - 1]) - fminf(volP[j], volP[j -1])); | |
} | |
v /= (float) lookahead * 2.0f; | |
if(v >= 0.1f && atLeast <= 0) { | |
atLeast = (int)minDuration; | |
wprintf(L"Whomp\n"); // silly output | |
} | |
// ugly but simple possibility to avaid overdrive | |
float normalizedResultLeft = leftChannel * 0.5f; | |
float normalizedResultRight = rightChannel * 0.5f; | |
if(atLeast-- > 0) { | |
float Whomp = sin(baseA * M_PI * 2) * 0.8 | |
+ sin(baseB * M_PI * 2) * 0.2 | |
+ sin(baseC * M_PI * 2) * 0.01; | |
// (sin(x * pi * 2) + sin(x * pi * 4)) * 0.57 | |
float x = (minDuration - (float)atLeast ) / minDuration; | |
float asdr = (sinf(x * M_PI * 2.0f) + sin(x * M_PI * 4.0f)) * 0.567; | |
normalizedResultLeft += Whomp * 0.5 * asdr; | |
normalizedResultRight += Whomp * 0.5 * asdr; | |
} | |
// map the mormalized data back to pa values | |
audioValues[lId] = (short) clampf( normalizedResultLeft * 32767.0f,-32767,32767); | |
audioValues[rId] = (short) clampf( normalizedResultRight * 32767.0f,-32767,32767); | |
} | |
}; | |
bool playing = sad_playStream(mStream); | |
sad_cleanupStream(mStream); | |
if(sadInitOk) | |
sad_exitPulseAudio(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment