Skip to content

Instantly share code, notes, and snippets.

@rnjacobs
Created February 26, 2021 07:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rnjacobs/091ed975fb7dd762f095bf3e6c9350e6 to your computer and use it in GitHub Desktop.
Save rnjacobs/091ed975fb7dd762f095bf3e6c9350e6 to your computer and use it in GitHub Desktop.
Using a serial port as a sound card with a 2nd order delta-sigma DAC
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <strings.h>
/* Written by Robert Jacobs sometime in 2008. Nothing new to me, I just
learned about delta-sigma modulation around that time.
Released under terms of CC0
Credit is appreciated but unnecessary.
*/
// Scaled up because we lose two bits out of every ten, so we need to be a
// little quieter so that the remaining 8 can carry the other weight
#define FBN -32768*10/8
#define FBP 32767*10/8
#define BKSZ 128
int main (int argc, char **argv) {
short in[BKSZ * 10];
unsigned char * out;
int i,t,p,d;
int ratio,counter;
int an,d1,i1,d2,i2,fb; /* Must be 32-bit to deal with 17-bit differenes */
/* Can't test stdout: ttyS0 is a tty. */
if (isatty(0)) {
fprintf(stderr,
"use: sd-2nd [us] < audioin > serialdev\n" \
" audioin should be-\n" \
" * the same sample rate as the serial dev's bitrate\n" \
" * us (default 1) is the upsample ratio\n" \
" * 16bit signed native-endian\n" \
" * headerless, single channel\n");
return 1|(isatty(0)?2:0)|(isatty(1)?4:0);
}
if (argc==1)
ratio=1;
else
ratio=atoi(argv[1]);
if (ratio<1) {
fprintf(stderr,"Can only upsample, not %d\n",ratio);
return 8;
}
out = (unsigned char *)malloc(BKSZ*ratio);
if (out==NULL) {
fprintf(stderr,"Dynamic memory allocation of %d kiBytes failed",2*ratio);
return 9;
}
an=d1=i1=d2=i2=fb=0;
/* Xn1 Serial: StartLow 0 1 2 ... X-2 X-1 StopHigh */
while (fread(in,20 * BKSZ,1,stdin)==1) { //BKSZ0 uint16s = 40960 bytes
bzero(out,BKSZ*ratio);
for (counter=ratio,d=p=0;p<BKSZ*ratio;p++) {
{ /* Start bit always low */
if (!counter) { counter=ratio; d++; } counter--;
an=in[d];
d1=an-fb;
i1+=d1;
d2=i1-fb;
i2+=d2;
fb=FBN;
}
for (i=0;i<8;i++) { /* Always assume 8N1 */
if (!counter) { counter=ratio; d++; } counter--;
an=in[d];
d1=an-fb;
i1+=d1;
d2=i1-fb;
i2+=d2;
if (i2>0) {
out[p] |= (1<<i);
fb=FBP;
} else
fb=FBN;
}
{ /* Stop bit always high */
if (!counter) { counter=ratio; d++; } counter--;
an=in[d];
d1=an-fb;
i1+=d1;
d2=i1-fb;
i2+=d2;
fb=FBP;
}
}
fwrite(out,BKSZ*ratio,1,stdout);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment