Compare commits
3 Commits
174f0df1d4
...
c72eca2ad8
Author | SHA1 | Date |
---|---|---|
Alexander Andreev | c72eca2ad8 | |
Alexander Andreev | d9cc37896f | |
Alexander Andreev | 97e5dae4db |
4
Makefile
4
Makefile
|
@ -16,10 +16,10 @@ CFLAGS = --std=c99 -D_POSIX_C_SOURCE=200112L -O3 -Wall -Werror -Wextra -pedantic
|
||||||
LDFLAGS += -lportaudio -lopus -lsodium
|
LDFLAGS += -lportaudio -lopus -lsodium
|
||||||
|
|
||||||
$(TARGET): $(OBJs)
|
$(TARGET): $(OBJs)
|
||||||
$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@
|
$(CC) $(LDFLAGS) $^ -o $@
|
||||||
|
|
||||||
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR)
|
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR)
|
||||||
$(CC) $(CFLAGS) $(LDFLAGS) -c $< -o $@
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
$(OBJ_DIR):
|
$(OBJ_DIR):
|
||||||
mkdir -p $@
|
mkdir -p $@
|
||||||
|
|
133
src/audio.c
133
src/audio.c
|
@ -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,10 +175,10 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
12
src/audio.h
12
src/audio.h
|
@ -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,10 +19,13 @@ 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);
|
||||||
|
|
||||||
#endif /* _AUDIO_H_ */
|
#endif /* _AUDIO_H_ */
|
||||||
|
|
|
@ -199,4 +199,4 @@ void crypt_session_destroy(crypt_session_t *const s) {
|
||||||
sodium_memzero(s->tx, CRYPT_SESS_KEY_LEN);
|
sodium_memzero(s->tx, CRYPT_SESS_KEY_LEN);
|
||||||
sodium_memzero(s->nonce, CRYPT_NONCE_LEN);
|
sodium_memzero(s->nonce, CRYPT_NONCE_LEN);
|
||||||
crypt_key_destroy(s->remote_key);
|
crypt_key_destroy(s->remote_key);
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,4 +57,4 @@ unsigned char *crypt_session_encrypt(crypt_session_t *const s, const unsigned ch
|
||||||
unsigned char *crypt_session_decrypt(crypt_session_t *const s, const unsigned char *const c, unsigned long long clen, unsigned long long *mlen);
|
unsigned char *crypt_session_decrypt(crypt_session_t *const s, const unsigned char *const c, unsigned long long clen, unsigned long long *mlen);
|
||||||
void crypt_session_destroy(crypt_session_t *const s);
|
void crypt_session_destroy(crypt_session_t *const s);
|
||||||
|
|
||||||
#endif /* _CRYPT_H_ */
|
#endif /* _CRYPT_H_ */
|
||||||
|
|
32
src/main.c
32
src/main.c
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,4 +16,4 @@ void net_destroy(net_t *n);
|
||||||
ssize_t net_send(net_t *const n, const char *const buf, int buf_len);
|
ssize_t net_send(net_t *const n, const char *const buf, int buf_len);
|
||||||
ssize_t net_recv(net_t *const n, void *const buf, size_t buf_len);
|
ssize_t net_recv(net_t *const n, void *const buf, size_t buf_len);
|
||||||
|
|
||||||
#endif /* _NET_H_ */
|
#endif /* _NET_H_ */
|
||||||
|
|
Loading…
Reference in New Issue