Hash :
17752a6c
Author :
Thomas de Grivel
Date :
2020-03-04T14:03:48
Downgrade to C89 = ANSI 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
/*
* Copyright 2018 Thomas de Grivel <thoxdg@gmail.com> +33614550127
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <limits.h>
#include <portaudio.h>
#include <stdio.h>
#include <strings.h>
#include "rtbuf.h"
#include "rtbuf_portaudio.h"
int g_initialized = 0;
int rtbuf_portaudio_output_start (s_rtbuf *rtb)
{
s_rtbuf_portaudio_output_data *data;
PaError err;
assert(rtb->proc->out_bytes == sizeof(*data));
data = (s_rtbuf_portaudio_output_data*) rtb->data;
if (!g_initialized) {
if (Pa_Initialize() != paNoError)
return rtbuf_err("portaudio_output_start: Pa_Initialize() failed");
g_initialized = 1;
}
err = Pa_OpenDefaultStream(&data->reserved.stream, /* stream pointer */
0, /* input channels */
RTBUF_PORTAUDIO_CHANNELS, /* output channels */
paInt16, /* sample format */
RTBUF_SIGNAL_SAMPLERATE, /* sample rate */
RTBUF_SIGNAL_SAMPLES, /* frames per buffer */
NULL, /* stream callback */
NULL); /* user data */
if (err != paNoError) {
rtbuf_err(Pa_GetErrorText(err));
return rtbuf_err("portaudio_output_start: Pa_OpenDefaultStream() failed");
}
err = Pa_StartStream(data->reserved.stream);
if (err != paNoError) {
rtbuf_err(Pa_GetErrorText(err));
return rtbuf_err("portaudio output start: Pa_StartStream() failed");
}
return 0;
}
int rtbuf_portaudio_output_stop (s_rtbuf *rtb)
{
s_rtbuf_portaudio_output_data *data;
data = (s_rtbuf_portaudio_output_data*) rtb->data;
if (data->reserved.stream) {
Pa_StopStream(data->reserved.stream);
Pa_CloseStream(data->reserved.stream);
data->reserved.stream = 0;
}
return 0;
}
int rtbuf_portaudio_output (s_rtbuf *rtb)
{
s_rtbuf_signal_fun in[RTBUF_PORTAUDIO_CHANNELS];
s_rtbuf_portaudio_output_data *data;
short *sample;
unsigned int i = 0;
unsigned int j = 0;
PaError err;
assert(rtb);
assert(rtb->data);
assert(rtb->proc);
while (j < RTBUF_PORTAUDIO_CHANNELS) {
rtbuf_signal_fun(rtb, j, &in[j]);
j++;
}
data = (s_rtbuf_portaudio_output_data*) rtb->data;
sample = data->samples;
/* printf("portaudio_output"); */
while (i < RTBUF_SIGNAL_SAMPLES) {
j = 0;
while (j < RTBUF_PORTAUDIO_CHANNELS) {
double in_ = in[j].sample_fun(in[j].signal, i);
in_ = clamp(-1.0, in_, 1.0);
if (in_ < 0.0)
in_ *= -SHRT_MIN;
else
in_ *= SHRT_MAX;
*sample = (short) in_;
sample++;
j++;
}
i++;
}
err = Pa_WriteStream(data->reserved.stream, data->samples, RTBUF_SIGNAL_SAMPLES);
if (err != paNoError) {
rtbuf_err(Pa_GetErrorText(err));
rtbuf_err("portaudio output: Pa_WriteStream failed");
}
/* printf("\n"); */
return 0;
}