mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 11:37:35 +00:00
149 lines
4.2 KiB
C
149 lines
4.2 KiB
C
#if 0
|
|
/*─────────────────────────────────────────────────────────────────╗
|
|
│ To the extent possible under law, Justine Tunney has waived │
|
|
│ all copyright and related or neighboring rights to this file, │
|
|
│ as it is written in the following disclaimers: │
|
|
│ • http://unlicense.org/ │
|
|
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
|
╚─────────────────────────────────────────────────────────────────*/
|
|
#endif
|
|
#include "dsp/core/core.h"
|
|
#include "libc/bits/bits.h"
|
|
#include "libc/calls/calls.h"
|
|
#include "libc/calls/struct/sigaction.h"
|
|
#include "libc/fmt/nf32.h"
|
|
#include "libc/log/check.h"
|
|
#include "libc/macros.internal.h"
|
|
#include "libc/runtime/runtime.h"
|
|
#include "libc/stdio/append.internal.h"
|
|
#include "libc/stdio/stdio.h"
|
|
#include "libc/sysv/consts/itimer.h"
|
|
#include "libc/sysv/consts/sig.h"
|
|
#include "libc/time/time.h"
|
|
|
|
/**
|
|
* @fileoverview experimental way to play audio in terminals
|
|
*
|
|
* This is an stdio application that prints audio samples. The terminal
|
|
* on the other end, needs to be able to understand the Nf sequences we
|
|
* use here, which should be invisible to the terminal sort of like out
|
|
* of band signalling.
|
|
*
|
|
* To play audio with a supporting terminal:
|
|
*
|
|
* make -j8 o//examples/ttyaudio.com
|
|
* wget https://justine.lol/numbers.s16
|
|
* o//examples/ttyaudio.com numbers.s16
|
|
*
|
|
* To reveal the inband ansi audio transmission:
|
|
*
|
|
* o//examples/ttyaudio.com numbers.s16 2>/dev/null |
|
|
* o//tool/viz/bing.com |
|
|
* o//tool/viz/fold.com
|
|
*
|
|
*/
|
|
|
|
#define CSI "s"
|
|
#define SGR1 "?80"
|
|
#define SGR2 "?81"
|
|
|
|
struct Ring {
|
|
int i; // read index
|
|
int j; // write index
|
|
int n; // total samples
|
|
short* p; // samples
|
|
};
|
|
|
|
struct Speaker {
|
|
int rate; // in hertz, e.g. 8000
|
|
int codec; // 0 = s16, 2 = µ-Law
|
|
int channels; // 1 = mono, 2 = stereo
|
|
struct Ring buf; // audio playback buffer
|
|
};
|
|
|
|
const int maxar = 31;
|
|
const int ptime = 20;
|
|
|
|
struct Speaker s;
|
|
|
|
void OnAlrm(int sig) {
|
|
}
|
|
|
|
void LoadAudioFile(struct Speaker* s, const char* path) {
|
|
int rc;
|
|
FILE* f;
|
|
short buf[1024];
|
|
if (!(f = fopen(path, "rb"))) {
|
|
fprintf(stderr, "failed to open file\n");
|
|
exit(1);
|
|
}
|
|
for (;;) {
|
|
rc = fread(buf, sizeof(short), sizeof(buf) / sizeof(short), f);
|
|
if (rc) {
|
|
s->buf.p = (short*)realloc(s->buf.p, (s->buf.n + rc) * sizeof(short));
|
|
memcpy(s->buf.p + s->buf.n, buf, rc * sizeof(short));
|
|
s->buf.n += rc;
|
|
} else if (ferror(f)) {
|
|
fprintf(stderr, "read error: %s\n", strerror(ferror(f)));
|
|
exit(2);
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
fclose(f);
|
|
}
|
|
|
|
int main(int argc, char* argv[]) {
|
|
if (argc < 2) return 1;
|
|
if (!isatty(0)) exit(1);
|
|
|
|
s.rate = 8000;
|
|
s.channels = 1;
|
|
s.codec = 0;
|
|
LoadAudioFile(&s, argv[1]);
|
|
|
|
char nf[21];
|
|
char* obuf = 0;
|
|
appendw(&obuf, READ16LE("\e%"));
|
|
appendd(&obuf, nf, EncodeNf32(nf, s.rate) - nf);
|
|
appendw(&obuf, '/');
|
|
appendd(&obuf, nf, EncodeNf32(nf, s.channels) - nf);
|
|
appendw(&obuf, '/');
|
|
appendd(&obuf, nf, EncodeNf32(nf, s.codec) - nf);
|
|
appendw(&obuf, '0');
|
|
write(1, obuf, appendz(obuf).i);
|
|
free(obuf);
|
|
|
|
struct sigaction sa = {.sa_handler = OnAlrm};
|
|
struct itimerval it = {{0, ptime * 1000}, {0, ptime * 1000}};
|
|
CHECK_NE(-1, sigaction(SIGALRM, &sa, 0));
|
|
CHECK_NE(-1, setitimer(ITIMER_REAL, &it, 0));
|
|
|
|
for (;;) {
|
|
char* p;
|
|
int count;
|
|
char nf[22];
|
|
int i, j, x;
|
|
char* obuf = 0;
|
|
int samps = s.rate / (1000 / ptime);
|
|
appendw(&obuf, READ16LE("\e "));
|
|
for (i = 0; i < samps; ++i) {
|
|
if (s.codec == 1) {
|
|
x = mulaw(s.buf.p[s.buf.i++]);
|
|
} else {
|
|
x = s.buf.p[s.buf.i++] & 0xffff;
|
|
}
|
|
*(p = EncodeNf32(nf, x)) = '/';
|
|
appendd(&obuf, nf, p + 1 - nf);
|
|
if (s.buf.i == s.buf.n) break;
|
|
}
|
|
appendw(&obuf, '0');
|
|
write(1, obuf, appendz(obuf).i);
|
|
free(obuf);
|
|
fprintf(stderr, "\r\e[K%d / %d", s.buf.i, s.buf.n);
|
|
fflush(stderr);
|
|
pause();
|
|
}
|
|
|
|
return 1;
|
|
}
|