Skip to content

Instantly share code, notes, and snippets.

@yousry
Created November 14, 2014 15:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yousry/82e81efb50e8027c7b8f to your computer and use it in GitHub Desktop.
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/)
#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