Add 5.1 surround sound support

This commit is contained in:
Cameron Gutman
2015-10-26 02:54:05 +00:00
parent af383eb371
commit 48f88f6d2f
5 changed files with 60 additions and 25 deletions

View File

@@ -20,30 +20,49 @@
#include "../audio.h"
#include <stdio.h>
#include <opus.h>
#include <opus_multistream.h>
#include <alsa/asoundlib.h>
#define CHECK_RETURN(f) if ((rc = f) < 0) { printf("Alsa error code %d\n", rc); exit(-1); }
#define SAMPLE_RATE 48000
#define CHANNEL_COUNT 2
#define MAX_CHANNEL_COUNT 6
#define FRAME_SIZE 240
const char* audio_device = "sysdefault";
static snd_pcm_t *handle;
static OpusDecoder* decoder;
static short pcmBuffer[FRAME_SIZE * CHANNEL_COUNT];
static OpusMSDecoder* decoder;
static short pcmBuffer[FRAME_SIZE * MAX_CHANNEL_COUNT];
static void alsa_renderer_init() {
static void alsa_renderer_init(int audioConfiguration, POPUS_MULTISTREAM_CONFIGURATION opusConfig) {
int rc;
decoder = opus_decoder_create(SAMPLE_RATE, CHANNEL_COUNT, &rc);
unsigned char alsaMapping[6];
/* The supplied mapping array has order: FL-FR-C-LFE-RL-RR
* ALSA expects the order: FL-FR-RL-RR-C-LFE
* We need copy the mapping locally and swap the channels around.
*/
alsaMapping[0] = opusConfig->mapping[0];
alsaMapping[1] = opusConfig->mapping[1];
if (opusConfig->channelCount == 6) {
alsaMapping[2] = opusConfig->mapping[4];
alsaMapping[3] = opusConfig->mapping[5];
alsaMapping[4] = opusConfig->mapping[2];
alsaMapping[5] = opusConfig->mapping[3];
}
decoder = opus_multistream_decoder_create(opusConfig->sampleRate,
opusConfig->channelCount,
opusConfig->streams,
opusConfig->coupledStreams,
alsaMapping,
&rc);
snd_pcm_hw_params_t *hw_params;
snd_pcm_sw_params_t *sw_params;
snd_pcm_uframes_t period_size = FRAME_SIZE * CHANNEL_COUNT * 2;
snd_pcm_uframes_t period_size = FRAME_SIZE * opusConfig->channelCount * 2;
snd_pcm_uframes_t buffer_size = 12 * period_size;
unsigned int sampleRate = SAMPLE_RATE;
unsigned int sampleRate = opusConfig->sampleRate;
/* Open PCM device for playback. */
CHECK_RETURN(snd_pcm_open(&handle, audio_device, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK))
@@ -54,7 +73,7 @@ static void alsa_renderer_init() {
CHECK_RETURN(snd_pcm_hw_params_set_access(handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED));
CHECK_RETURN(snd_pcm_hw_params_set_format(handle, hw_params, SND_PCM_FORMAT_S16_LE));
CHECK_RETURN(snd_pcm_hw_params_set_rate_near(handle, hw_params, &sampleRate, NULL));
CHECK_RETURN(snd_pcm_hw_params_set_channels(handle, hw_params, CHANNEL_COUNT));
CHECK_RETURN(snd_pcm_hw_params_set_channels(handle, hw_params, opusConfig->channelCount));
CHECK_RETURN(snd_pcm_hw_params_set_buffer_size_near(handle, hw_params, &buffer_size));
CHECK_RETURN(snd_pcm_hw_params_set_period_size_near(handle, hw_params, &period_size, NULL));
CHECK_RETURN(snd_pcm_hw_params(handle, hw_params));
@@ -73,7 +92,7 @@ static void alsa_renderer_init() {
static void alsa_renderer_cleanup() {
if (decoder != NULL)
opus_decoder_destroy(decoder);
opus_multistream_decoder_destroy(decoder);
if (handle != NULL) {
snd_pcm_drain(handle);
@@ -82,7 +101,7 @@ static void alsa_renderer_cleanup() {
}
static void alsa_renderer_decode_and_play_sample(char* data, int length) {
int decodeLen = opus_decode(decoder, data, length, pcmBuffer, FRAME_SIZE, 0);
int decodeLen = opus_multistream_decode(decoder, data, length, pcmBuffer, FRAME_SIZE, 0);
if (decodeLen > 0) {
int rc = snd_pcm_writei(handle, pcmBuffer, decodeLen);
if (rc == -EPIPE)

View File

@@ -23,27 +23,34 @@
#include <SDL_audio.h>
#include <stdio.h>
#include <opus.h>
#include <opus_multistream.h>
#define SAMPLE_RATE 48000
#define CHANNEL_COUNT 2
#define MAX_CHANNEL_COUNT 6
#define FRAME_SIZE 240
static OpusDecoder* decoder;
static short pcmBuffer[FRAME_SIZE * CHANNEL_COUNT];
static OpusMSDecoder* decoder;
static short pcmBuffer[FRAME_SIZE * MAX_CHANNEL_COUNT];
static SDL_AudioDeviceID dev;
static int channelCount;
static void sdl_renderer_init() {
static void sdl_renderer_init(int audioConfiguration, POPUS_MULTISTREAM_CONFIGURATION opusConfig) {
int rc;
decoder = opus_decoder_create(SAMPLE_RATE, CHANNEL_COUNT, &rc);
decoder = opus_multistream_decoder_create(opusConfig->sampleRate,
opusConfig->channelCount,
opusConfig->streams,
opusConfig->coupledStreams,
opusConfig->mapping,
&rc);
channelCount = opusConfig->channelCount;
SDL_InitSubSystem(SDL_INIT_AUDIO);
SDL_AudioSpec want, have;
SDL_zero(want);
want.freq = SAMPLE_RATE;
want.freq = opusConfig->sampleRate;
want.format = AUDIO_S16LSB;
want.channels = CHANNEL_COUNT;
want.channels = opusConfig->channelCount;
want.samples = 4096;
dev = SDL_OpenAudioDevice(NULL, 0, &want, &have, SDL_AUDIO_ALLOW_FORMAT_CHANGE);
@@ -58,15 +65,15 @@ static void sdl_renderer_init() {
static void sdl_renderer_cleanup() {
if (decoder != NULL)
opus_decoder_destroy(decoder);
opus_multistream_decoder_destroy(decoder);
SDL_CloseAudioDevice(dev);
}
static void sdl_renderer_decode_and_play_sample(char* data, int length) {
int decodeLen = opus_decode(decoder, data, length, pcmBuffer, FRAME_SIZE, 0);
int decodeLen = opus_multistream_decode(decoder, data, length, pcmBuffer, FRAME_SIZE, 0);
if (decodeLen > 0) {
SDL_QueueAudio(dev, pcmBuffer, decodeLen * CHANNEL_COUNT * sizeof(short));
SDL_QueueAudio(dev, pcmBuffer, decodeLen * channelCount * sizeof(short));
} else {
printf("Opus error from decode: %d\n", decodeLen);
}