RISC-V/V003/midi/linux/pcmdma.cpp

80 lines
2.1 KiB
C++
Raw Normal View History

2024-04-08 20:55:20 +02:00
#include "pcmdma.h"
#include <pthread.h>
#include <alsa/asoundlib.h>
#include <signal.h>
struct Sample {
short l;
short r;
}__attribute__((packed));
static constexpr unsigned BufLen = FULL_LEN;
static const char *device = "default";
static snd_pcm_t *handle;
static int open_alsa_device (int channels, int srate) {
int err;
if ((err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
printf("Playback open error: %s\n", snd_strerror(err));
return 0;
}
if ((err = snd_pcm_set_params(handle,
SND_PCM_FORMAT_S16_LE,
SND_PCM_ACCESS_RW_INTERLEAVED,
channels,
srate,
1,
500000)) < 0) { /* 0.5sec */
printf("Playback open error: %s\n", snd_strerror(err));
return 0;
}
return 1;
}
int alsa_write (const void * buf, int len) {
snd_pcm_sframes_t frames;
int err = 0;
frames = snd_pcm_writei(handle, buf, len);
if (frames < 0)
frames = snd_pcm_recover(handle, frames, 0);
if (frames < 0) {
printf("snd_pcm_writei failed: %s\n", snd_strerror(err));
return 0;
}
if (frames > 0 && frames < (long)sizeof(buf))
printf("Short write (expected %i, wrote %li)\n", len, frames);
return len;
}
void sig_handler (int signum) {
printf(" - Received signal %d\n", signum);
::exit (0);
}
static constexpr int CC = MAXPWM / 2;
static pthread_t rc;
void * WriteHandler (void * data) {
printf ("Start thread\n");
PcmDma * pA = (PcmDma *) data;
Sample buf [BufLen];
uint16_t * pbuf = pA->getBuff();
for (;;) {
pA->send (false);
pA->send (true);
//printf ("pass\n");
for (unsigned i=0; i<BufLen; i++) {
const short s = (pbuf [i] - CC) * 32;
buf[i].l = s; buf[i].r = s;
}
alsa_write (buf, BufLen);
}
return NULL;
}
PcmDma::PcmDma() noexcept : pL(buffer), pH(buffer + HALF_LEN), src(nullptr) {
signal (SIGINT, sig_handler);
open_alsa_device(2, 24000);
pthread_create (&rc, NULL, WriteHandler, this);
}