| 23 | |
| 24 | static int gNumNoInputs = 0; |
| 25 | static int callback(const void *inputBuffer, void *outputBuffer, |
| 26 | unsigned long framesPerBuffer, |
| 27 | const PaStreamCallbackTimeInfo *timeInfo, |
| 28 | PaStreamCallbackFlags statusFlags, void *userData) { |
| 29 | SAMPLE* out = (SAMPLE *)outputBuffer; |
| 30 | const SAMPLE *in = (const SAMPLE *)inputBuffer; |
| 31 | (void)timeInfo; /* Prevent unused variable warnings. */ |
| 32 | (void)statusFlags; |
| 33 | (void)userData; |
| 34 | |
| 35 | Buffer *buffer = reinterpret_cast<Buffer *>(userData); |
| 36 | size_t timeIndex = (timeInfo->currentTime /* in seconds */ * SAMPLE_RATE) / |
| 37 | FRAMES_PER_BUFFER * FRAMES_PER_BUFFER; |
| 38 | |
| 39 | int scale = 1; |
| 40 | size_t reverseIndex = buffer->size - scale * timeIndex; |
| 41 | |
| 42 | if (inputBuffer == NULL) { |
| 43 | for (int i = 0; i < framesPerBuffer; i++) { |
| 44 | *out++ = sigmoid(0); |
| 45 | *out++ = sigmoid(0); |
| 46 | } |
| 47 | gNumNoInputs += 1; |
| 48 | } else { |
| 49 | for (int i = 0; i < framesPerBuffer; i++) { |
| 50 | size_t playHead0 = (timeIndex + i) % buffer->size; |
| 51 | size_t playHead1 = (reverseIndex - scale * i ) % buffer->size; // reverse playhead |
| 52 | |
| 53 | SAMPLE sample = *in++; /* MONO input */ |
| 54 | |
| 55 | float value = sigmoid(0.5 * sample + 0.5 * buffer->buffer[playHead1]); |
| 56 | |
| 57 | *out++ = value; /* LEFT */ |
| 58 | *out++ = value; /* RIGHT */ |
| 59 | buffer->buffer[playHead0] = sample; |
| 60 | |
| 61 | printf("\033[H\033[H\n\nTime = %f\nplayHead0 = %zu\nplayHead1 (reverse) " |
| 62 | "index=%zu\noutput value=%.2f\ninput value=%.2f\nplayhead1 value =%.2f\n", |
| 63 | timeInfo->currentTime, playHead0, playHead1, value, |
| 64 | sample, |
| 65 | buffer->buffer[playHead1]); |
| 66 | } |
| 67 | } |
| 68 | |
| 69 | return paContinue; |
| 70 | } |
| 71 | |
| 72 | void check(bool condition, const char *message) { |
| 73 | if (!condition) { |