1
0

Made separate streams for in and out sound. WIll be very handy for muting a microphone and your companion.

This commit is contained in:
Alexander Andreev 2024-03-25 01:05:29 +04:00
parent d9cc37896f
commit c72eca2ad8
Signed by: Arav
GPG Key ID: 25969B23DCB5CA34
3 changed files with 133 additions and 38 deletions

View File

@ -1,17 +1,52 @@
#include "audio.h" #include "audio.h"
#include <portaudio.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
int audio_init(audio_t *aud, int channels, int sample_rate, int frame_size) { int audio_init_soundsystem(void) {
PaError pa_err; PaError pa_err;
int opus_err;
if ((pa_err = Pa_Initialize()) != paNoError) { if ((pa_err = Pa_Initialize()) != paNoError) {
fprintf(stderr, "Cannot initialise PortAudio: %s\n", Pa_GetErrorText(pa_err)); fprintf(stderr, "Cannot initialise PortAudio: %s\n", Pa_GetErrorText(pa_err));
return -1; return -1;
} }
return 0;
}
int audio_terminate_soundsystem(void) {
PaError pa_err;
if ((pa_err = Pa_Terminate()) != paNoError) {
fprintf(stderr, "Cannot terminate PortAudio: %s\n", Pa_GetErrorText(pa_err));
return -1;
}
return 0;
}
int audio_init_default(audio_t *aud, int channels, int sample_rate, int frame_size) {
PaError pa_err;
int opus_err;
if ((pa_err = Pa_OpenDefaultStream(&aud->stream_in, channels, 0, AUDIO_SAMPLE_FORMAT,
sample_rate, frame_size, NULL, NULL)) != paNoError) {
fprintf(stderr, "Cannot open an input PortAudio stream: %s\n", Pa_GetErrorText(pa_err));
return -1;
}
if ((pa_err = Pa_OpenDefaultStream(&aud->stream_out, 0, channels, AUDIO_SAMPLE_FORMAT,
sample_rate, frame_size, NULL, NULL)) != paNoError) {
fprintf(stderr, "Cannot open an input PortAudio stream: %s\n", Pa_GetErrorText(pa_err));
return -1;
}
aud->buffer_size = frame_size * channels;
aud->buffer = (audio_sample_t *)malloc(aud->buffer_size * sizeof(audio_sample_t));
if (aud->buffer == NULL)
return -1;
aud->opus_enc = opus_encoder_create(sample_rate, channels, OPUS_APPLICATION_VOIP, &opus_err); aud->opus_enc = opus_encoder_create(sample_rate, channels, OPUS_APPLICATION_VOIP, &opus_err);
if (opus_err != OPUS_OK) { if (opus_err != OPUS_OK) {
fprintf(stderr, "An Opus encoder cannot be created: %s\n", opus_strerror(opus_err)); fprintf(stderr, "An Opus encoder cannot be created: %s\n", opus_strerror(opus_err));
@ -24,44 +59,34 @@ int audio_init(audio_t *aud, int channels, int sample_rate, int frame_size) {
return -1; return -1;
} }
if ((pa_err = Pa_OpenDefaultStream(&aud->stream, channels, channels, AUDIO_SAMPLE_FORMAT,
sample_rate, frame_size, NULL, NULL)) != paNoError) {
fprintf(stderr, "Cannot open a PortAudio stream: %s\n", Pa_GetErrorText(pa_err));
return -1;
}
aud->buffer_size = frame_size * channels;
aud->buffer = (audio_sample_t *)malloc(aud->buffer_size * sizeof(audio_sample_t));
if (aud->buffer == NULL)
return -1;
if ((pa_err = Pa_StartStream(aud->stream)) != paNoError) {
fprintf(stderr, "Cannot start a PortAudio stream: %s\n", Pa_GetErrorText(pa_err));
free(aud->buffer);
return -1;
}
return 0; return 0;
} }
int audio_destroy(audio_t *aud) { int audio_destroy(audio_t *aud) {
PaError pa_err; PaError pa_err;
if (aud->stream) { if (aud->stream_in != NULL) {
if ((pa_err = Pa_StopStream(aud->stream)) != paNoError) { if ((pa_err = Pa_StopStream(aud->stream_in)) != paNoError && pa_err != paStreamIsStopped) {
fprintf(stderr, "Cannot stop a PortAudio stream: %s\n", Pa_GetErrorText(pa_err)); fprintf(stderr, "Cannot stop an input PortAudio stream: %s\n", Pa_GetErrorText(pa_err));
return -1; return -1;
} }
if ((pa_err = Pa_CloseStream(aud->stream)) != paNoError) { if ((pa_err = Pa_CloseStream(aud->stream_in)) != paNoError) {
fprintf(stderr, "Cannot close a PortAudio stream: %s\n", Pa_GetErrorText(pa_err)); fprintf(stderr, "Cannot close an input PortAudio stream: %s\n", Pa_GetErrorText(pa_err));
return -1; return -1;
} }
} }
if ((pa_err = Pa_Terminate()) != paNoError) { if (aud->stream_out != NULL) {
fprintf(stderr, "Cannot terminate PortAudio: %s\n", Pa_GetErrorText(pa_err)); if ((pa_err = Pa_StopStream(aud->stream_out)) != paNoError) {
return -1; fprintf(stderr, "Cannot stop an output PortAudio stream: %s\n", Pa_GetErrorText(pa_err));
return -1;
}
if ((pa_err = Pa_CloseStream(aud->stream_out)) != paNoError) {
fprintf(stderr, "Cannot close an output PortAudio stream: %s\n", Pa_GetErrorText(pa_err));
return -1;
}
} }
if (aud->buffer) if (aud->buffer)
@ -76,10 +101,58 @@ int audio_destroy(audio_t *aud) {
return 0; return 0;
} }
int audio_stream_input_toggle(audio_t *aud) {
PaError pa_err;
if ((pa_err = Pa_IsStreamStopped(aud->stream_in)) != 0) {
if (pa_err < 0 && pa_err != paStreamIsStopped) {
fprintf(stderr, "Cannot get state of an input PortAudio stream: %s\n", Pa_GetErrorText(pa_err));
return -1;
}
if ((pa_err = Pa_StartStream(aud->stream_in)) != paNoError) {
fprintf(stderr, "Cannot start an input PortAudio stream: %s\n", Pa_GetErrorText(pa_err));
free(aud->buffer);
return -1;
}
} else {
if ((pa_err = Pa_StopStream(aud->stream_in)) != paNoError) {
fprintf(stderr, "Cannot stop an input PortAudio stream: %s\n", Pa_GetErrorText(pa_err));
return -1;
}
}
return 0;
}
int audio_stream_output_toggle(audio_t *aud) {
PaError pa_err;
if ((pa_err = Pa_IsStreamStopped(aud->stream_out)) != 0) {
if (pa_err < 0) {
fprintf(stderr, "Cannot get state of an output PortAudio stream: %s\n", Pa_GetErrorText(pa_err));
return -1;
}
if ((pa_err = Pa_StartStream(aud->stream_out)) != paNoError) {
fprintf(stderr, "Cannot start an output PortAudio stream: %s\n", Pa_GetErrorText(pa_err));
free(aud->buffer);
return -1;
}
} else {
if ((pa_err = Pa_StopStream(aud->stream_out)) != paNoError) {
fprintf(stderr, "Cannot stop an output PortAudio stream: %s\n", Pa_GetErrorText(pa_err));
return -1;
}
}
return 0;
}
int audio_read(audio_t *aud, unsigned char *output, int output_len) { int audio_read(audio_t *aud, unsigned char *output, int output_len) {
PaError pa_err; PaError pa_err;
if ((pa_err = Pa_ReadStream(aud->stream, aud->buffer, aud->buffer_size)) != paNoError) { if ((pa_err = Pa_ReadStream(aud->stream_in, aud->buffer, aud->buffer_size)) != paNoError) {
fprintf(stderr, "Cannot read from a PortAudio stream: %s\n", Pa_GetErrorText(pa_err)); fprintf(stderr, "Cannot read from a PortAudio stream: %s\n", Pa_GetErrorText(pa_err));
return -1; return -1;
} }
@ -102,7 +175,7 @@ int audio_write(audio_t *aud, const unsigned char *input, int input_len) {
return -1; return -1;
} }
if ((pa_err = Pa_WriteStream(aud->stream, aud->buffer, aud->buffer_size)) != paNoError) { if ((pa_err = Pa_WriteStream(aud->stream_out, aud->buffer, aud->buffer_size)) != paNoError) {
fprintf(stderr, "Cannot write to a PortAudio stream: %s\n", Pa_GetErrorText(pa_err)); fprintf(stderr, "Cannot write to a PortAudio stream: %s\n", Pa_GetErrorText(pa_err));
return -1; return -1;
} }

View File

@ -7,8 +7,11 @@
#define AUDIO_SAMPLE_FORMAT paFloat32 #define AUDIO_SAMPLE_FORMAT paFloat32
typedef float audio_sample_t; typedef float audio_sample_t;
int audio_init_soundsystem(void);
int audio_terminate_soundsystem(void);
typedef struct audio_t { typedef struct audio_t {
PaStream *stream; PaStream *stream_in, *stream_out;
OpusEncoder *opus_enc; OpusEncoder *opus_enc;
OpusDecoder *opus_dec; OpusDecoder *opus_dec;
@ -16,9 +19,12 @@ typedef struct audio_t {
int buffer_size; int buffer_size;
} audio_t; } audio_t;
int audio_init(audio_t *aud, int channels, int sample_rate, int frame_size); int audio_init_default(audio_t *aud, int channels, int sample_rate, int frame_size);
int audio_destroy(audio_t *aud); int audio_destroy(audio_t *aud);
int audio_stream_input_toggle(audio_t *aud);
int audio_stream_output_toggle(audio_t *aud);
int audio_read(audio_t *aud, unsigned char *output, int output_len); int audio_read(audio_t *aud, unsigned char *output, int output_len);
int audio_write(audio_t *aud, const unsigned char *input, int input_len); int audio_write(audio_t *aud, const unsigned char *input, int input_len);

View File

@ -1,3 +1,4 @@
#include <portaudio.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -7,7 +8,7 @@
#define CHANNELS 1 #define CHANNELS 1
#define SAMPLE_RATE 48000 #define SAMPLE_RATE 48000
#define FRAMES_PER_BUFFFER 480 #define FRAMES_PER_BUFFFER 960
#define BUF_SIZE (FRAMES_PER_BUFFFER * CHANNELS) #define BUF_SIZE (FRAMES_PER_BUFFFER * CHANNELS)
@ -109,31 +110,43 @@ int main(int argc, char **argv) {
goto cleanup; goto cleanup;
} }
if (audio_init_soundsystem() == -1) {
rt = -1;
goto cleanup;
}
audio_t aud; audio_t aud;
unsigned char buf[BUF_SIZE]; unsigned char buf[BUF_SIZE];
memset(buf, 0, BUF_SIZE); memset(buf, 0, BUF_SIZE);
audio_init(&aud, CHANNELS, SAMPLE_RATE, FRAMES_PER_BUFFFER); audio_init_default(&aud, CHANNELS, SAMPLE_RATE, FRAMES_PER_BUFFFER);
if (audio_stream_input_toggle(&aud) == -1) {
rt = -1;
goto cleanup;
}
if (audio_stream_output_toggle(&aud) == -1) {
rt = -1;
goto cleanup;
}
unsigned char *c = NULL, *m = NULL; unsigned char *c = NULL, *m = NULL;
unsigned long long cl = 0, ml = 0; unsigned long long cl = 0, ml = 0;
printf("Listening... "); printf("Listening... ");
for (int i = 0; i < (20 * SAMPLE_RATE)/FRAMES_PER_BUFFFER; ++i) { for (int i = 0; i < (10 * SAMPLE_RATE)/FRAMES_PER_BUFFFER; ++i) {
audio_read(&aud, buf, BUF_SIZE); audio_read(&aud, buf, BUF_SIZE);
c = crypt_session_encrypt(&os, buf, BUF_SIZE, &cl); c = crypt_session_encrypt(&os, buf, BUF_SIZE, &cl);
int sc = net_send(&nc, (const char *)c, cl); net_send(&nc, (const char *)c, cl);
int rc = net_recv(&ns, c, cl); net_recv(&ns, c, cl);
fprintf(stderr, "%d %d\n", sc, rc);
m = crypt_session_decrypt(&rs, c, cl, &ml); m = crypt_session_decrypt(&rs, c, cl, &ml);
audio_write(&aud, m, ml); audio_write(&aud, m, ml);
free(c); free(m); free(c); free(m);
} }
printf("Done!\n"); printf("Done!\n");
audio_destroy(&aud);
cleanup: cleanup:
free(oh); free(oh);
@ -154,5 +167,8 @@ cleanup:
net_destroy(&ns); net_destroy(&ns);
net_destroy(&nc); net_destroy(&nc);
audio_destroy(&aud);
audio_terminate_soundsystem();
return rt; return rt;
} }