Commit 8e4feb49 authored by Miller Puckette's avatar Miller Puckette
Browse files

Fix to sigmund~ and 3-byte alsa support

parent ad2d836f
......@@ -1457,7 +1457,7 @@ static void *sigmund_new(t_symbol *s, long ac, t_atom *av)
dsp_setup((t_pxobject *)x, 1);
object_obex_store(x, gensym("dumpout"), outlet_new(x, NULL));
for (i = 0; i < ac; i++) FIXME
for (i = 0; i < ac; i++)
if (av[i].a_type == A_SYM)
{
char *s = av[i].a_w.w_sym->s_name;
......
......@@ -25,6 +25,7 @@
#include <sched.h>
#include <sys/mman.h>
#include "s_audio_alsa.h"
#include <endian.h>
/* Defines */
#define DEBUG(x) x
......@@ -117,17 +118,33 @@ static int alsaio_setup(t_alsa_dev *dev, int out, int *channels, int *rate,
if (err < 0)
return (-1);
check_error(err, "snd_pcm_hw_params_set_access");
#if 0 /* enable this to print out which formats are available */
{
int i;
for (i = 0; i <= SND_PCM_FORMAT_LAST; i++)
fprintf(stderr, "%d -> %d\n",
i, snd_pcm_hw_params_test_format(dev->a_handle, hw_params, i));
}
#endif
/* Try to set 32 bit format first */
err = snd_pcm_hw_params_set_format(dev->a_handle,
hw_params, SND_PCM_FORMAT_S32);
if (err < 0)
{
/* fprintf(stderr,
"PD-ALSA: 32 bit format not available - using 16\n"); */
"PD-ALSA: 32 bit format not available - trying 24\n"); */
err = snd_pcm_hw_params_set_format(dev->a_handle, hw_params,
SND_PCM_FORMAT_S16);
check_error(err, "snd_pcm_hw_params_set_format");
dev->a_sampwidth = 2;
SND_PCM_FORMAT_S24_3LE);
if (err < 0)
{
/* fprintf(stderr,
"PD-ALSA: 32/24 bit format not available - using 16\n"); */
err = snd_pcm_hw_params_set_format(dev->a_handle, hw_params,
SND_PCM_FORMAT_S16);
check_error(err, "snd_pcm_hw_params_set_format");
dev->a_sampwidth = 2;
}
else dev->a_sampwidth = 3;
}
else dev->a_sampwidth = 4;
......@@ -436,7 +453,32 @@ int alsa_send_dacs(void)
for (j = ch, k = DEFDACBLKSIZE; k--; j += thisdevchans)
((t_alsa_sample32 *)alsa_snd_buf)[j] = 0;
}
else
else if (alsa_outdev[iodev].a_sampwidth == 3)
{
for (i = 0; i < chans; i++, ch++, fp1 += DEFDACBLKSIZE)
for (j = ch, k = DEFDACBLKSIZE, fp2 = fp1; k--;
j += thisdevchans, fp2++)
{
int s = *fp2 * 8388352.;
if (s > 8388351)
s = 8388351;
else if (s < -8388351)
s = -8388351;
#if BYTE_ORDER == LITTLE_ENDIAN
((char *)(alsa_snd_buf))[3*j] = (s & 255);
((char *)(alsa_snd_buf))[3*j+1] = ((s>>8) & 255);
((char *)(alsa_snd_buf))[3*j+2] = ((s>>16) & 255);
#else
fprintf(stderr("big endian 24-bit not supported");
#endif
}
for (; i < thisdevchans; i++, ch++)
for (j = ch, k = DEFDACBLKSIZE; k--; j += thisdevchans)
((char *)(alsa_snd_buf))[3*j] =
((char *)(alsa_snd_buf))[3*j+1] =
((char *)(alsa_snd_buf))[3*j+2] = 0;
}
else /* 16 bit samples */
{
for (i = 0; i < chans; i++, ch++, fp1 += DEFDACBLKSIZE)
for (j = ch, k = DEFDACBLKSIZE, fp2 = fp1; k--;
......@@ -525,6 +567,23 @@ int alsa_send_dacs(void)
* (1./ INT32_MAX);
}
}
else if (alsa_indev[iodev].a_sampwidth == 3)
{
#if BYTE_ORDER == LITTLE_ENDIAN
for (i = 0; i < chans; i++, ch++, fp1 += DEFDACBLKSIZE)
{
for (j = ch, k = DEFDACBLKSIZE, fp2 = fp1; k--;
j += thisdevchans, fp2++)
*fp2 = ((float) (
(((unsigned char *)alsa_snd_buf)[3*j] << 8)
| (((unsigned char *)alsa_snd_buf)[3*j+1] << 16)
| (((unsigned char *)alsa_snd_buf)[3*j+2] << 24)))
* (1./ INT32_MAX);
}
#else
fprintf(stderr("big endian 24-bit not supported");
#endif
}
else
{
for (i = 0; i < chans; i++, ch++, fp1 += DEFDACBLKSIZE)
......
......@@ -11,6 +11,7 @@
#include "s_stuff.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <portaudio.h>
#include "s_audio_pablio.h"
......@@ -29,6 +30,34 @@ static t_audiocallback pa_callback;
int pa_foo;
static void pa_init(void)
{
static int initialized;
if (!initialized)
{
/* Initialize PortAudio */
/* for some reason Pa_Initialize(0 closes file descriptor 1.
As a workaround, dup it to another number and dup2 it back
afterward. */
int newfd = dup(1);
int err = Pa_Initialize();
if (newfd >= 0)
{
dup2(newfd, 1);
close(newfd);
}
if ( err != paNoError )
{
fprintf( stderr,
"Error number %d occured initializing portaudio\n",
err);
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return;
}
initialized = 1;
}
}
static int pa_lowlevel_callback(const void *inputBuffer,
void *outputBuffer, unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo *outTime, PaStreamCallbackFlags myflags,
......@@ -155,25 +184,11 @@ int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin,
int indeviceno, int outdeviceno, t_audiocallback callbackfn)
{
PaError err;
static int initialized;
int j, devno, pa_indev = 0, pa_outdev = 0;
pa_callback = callbackfn;
/* fprintf(stderr, "open callback %d\n", (callbackfn != 0)); */
if (!initialized)
{
/* Initialize PortAudio */
int err = Pa_Initialize();
if ( err != paNoError )
{
fprintf( stderr,
"Error number %d occured initializing portaudio\n",
err);
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return (1);
}
initialized = 1;
}
pa_init();
/* post("in %d out %d rate %d device %d", inchans, outchans, rate, deviceno); */
if (inchans > MAX_PA_CHANS)
{
......@@ -349,7 +364,7 @@ void pa_listdevs(void) /* lifted from pa_devs.c in portaudio */
int numDevices;
const PaDeviceInfo *pdi;
PaError err;
Pa_Initialize();
pa_init();
numDevices = Pa_GetDeviceCount();
if( numDevices < 0 )
{
......@@ -390,7 +405,7 @@ void pa_getdevs(char *indevlist, int *nindevs,
int i, nin = 0, nout = 0, ndev;
*canmulti = 1; /* one dev each for input and output */
Pa_Initialize();
pa_init();
ndev = Pa_GetDeviceCount();
for (i = 0; i < ndev; i++)
{
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment