Created
February 26, 2021 07:28
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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