-
Notifications
You must be signed in to change notification settings - Fork 2
/
musicplayer.c
125 lines (97 loc) · 2.87 KB
/
musicplayer.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// Music Player - Anfractuosity
// https://github.com/anfractuosity/musicplayer
//
// based on the work from
// https://github.com/fulldecent/system-bus-radio Copyright 2016 William Entriken
#include <stdio.h>
#include <emmintrin.h>
#include <math.h>
#include<stdint.h>
#include<time.h>
#include<math.h>
#include<sndfile.h>
__m128i reg;
__m128i reg_zero;
__m128i reg_one;
#define NSEC_PER_SEC 1000000000 /* nanoseconds per second */
uint64_t mach_absolute_time(){
struct timespec start, end;
clock_gettime(CLOCK_MONOTONIC, &start); /* mark start time */
return (uint64_t)start.tv_sec * NSEC_PER_SEC + start.tv_nsec;
}
// Derrived from http://dlbeer.co.nz/articles/pdm.html
unsigned int * pdm(unsigned int *x,int len){
unsigned *y=malloc(len*sizeof(int));
unsigned int n = 0;
unsigned int quant_error = 0;
for (n=0;n<len;n++){
quant_error += x[n];
if (quant_error >= 65535) {
quant_error -= 65535;
y[n] = 1;
continue;
}
y[n] = 0;
}
return y;
}
static inline void pdm_signal(int *pdm,int len,int samplerate) {
int i = 0;
for (i=0;i<len;i++){
double time = 1.0 / (double)samplerate;
uint64_t start = mach_absolute_time();
uint64_t end = start + time * NSEC_PER_SEC;
if(pdm[i] == 1)
while (mach_absolute_time() < end) {
_mm_stream_si128(®, reg_one);
_mm_stream_si128(®, reg_zero);
}
else
while (mach_absolute_time() < end) {
}
}
}
// From http://beej.us/blog/data/digital-sound/
int remap_level_to_signed_16_bit(float v)
{
long r;
// clamp values:
if (v > 1.0) { v = 1.0; }
else if (v < -1.0) { v = -1.0; }
v += 1.0; // remap from [-1.0,1.0] to [0.0,2.0]
v /= 2; // remap from [0.0,2.0] to [0.0,1.0]
r = v * 65535; // remap from [0.0,1.0] to [0,65535]
return r;
}
int main ( int argc, char **argv ) {
if(argc != 2){
printf("Need to pass audio file sampled at around 1 000 000 Hz\n");
return 1;
}else{
printf("Attempting to load file: %s\n",argv[1]);
}
SNDFILE *infile;
SF_INFO sfinfo ;
int readcount ;
if (! (infile = sf_open (argv[1], SFM_READ, &sfinfo))){
/* Open failed so print an error message. */
printf ("Not able to open input file %s.\n", argv[1]) ;
/* Print the error message from libsndfile. */
puts (sf_strerror (NULL)) ;
return 1 ;
}
if (sfinfo.channels > 1){
printf ("Not able to process more than 1 channels\n") ;
return 1 ;
}
double *data = malloc(sfinfo.frames*sizeof(double)) ;
unsigned int c;
readcount = sf_read_double (infile, data,sfinfo.frames);
unsigned int *nout = malloc(sizeof(int)*readcount);
for(c=0;c<readcount;c++){
nout[c] = remap_level_to_signed_16_bit(data[c]);
}
unsigned int* out = pdm(nout,readcount);
printf("Playing song at Sample Rate: %dHz\n",sfinfo.samplerate);
pdm_signal(out,readcount,sfinfo.samplerate);
}