summaryrefslogtreecommitdiff
path: root/sys/src
diff options
context:
space:
mode:
authorSigrid <ftrvxmtrx@gmail.com>2021-01-11 15:45:12 +0100
committerSigrid <ftrvxmtrx@gmail.com>2021-01-11 15:45:12 +0100
commitce82f6750c5d98968259b80614643ed63b972ea3 (patch)
treeb3fe6d83bb1abf34129f1771810567ce2ac7b372 /sys/src
parent10237a22f189d304668283fb82870b36144d4d1b (diff)
audio/flacenc
Diffstat (limited to 'sys/src')
-rw-r--r--sys/src/cmd/audio/flacenc/flacenc.c148
-rw-r--r--sys/src/cmd/audio/flacenc/mkfile21
-rw-r--r--sys/src/cmd/audio/mkfile2
3 files changed, 170 insertions, 1 deletions
diff --git a/sys/src/cmd/audio/flacenc/flacenc.c b/sys/src/cmd/audio/flacenc/flacenc.c
new file mode 100644
index 000000000..f67830e0f
--- /dev/null
+++ b/sys/src/cmd/audio/flacenc/flacenc.c
@@ -0,0 +1,148 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#define _PLAN9_SOURCE
+#include <utf.h>
+#include <lib9.h>
+#include "FLAC/stream_encoder.h"
+#include "FLAC/metadata.h"
+
+static FLAC__StreamEncoderReadStatus
+encwrite(FLAC__StreamEncoder *enc, FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame, void *client_data)
+{
+ return fwrite(buffer, 1, bytes, stdout) != bytes ?
+ FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR :
+ FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
+}
+
+static FLAC__StreamEncoderSeekStatus
+encseek(FLAC__StreamEncoder *enc, FLAC__uint64 absolute_byte_offset, void *client_data)
+{
+ return fseeko(stdout, absolute_byte_offset, SEEK_SET) != absolute_byte_offset ?
+ FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED :
+ FLAC__STREAM_ENCODER_SEEK_STATUS_OK;
+}
+
+static FLAC__StreamEncoderTellStatus
+enctell(FLAC__StreamEncoder *enc, FLAC__uint64 *absolute_byte_offset, void *client_data)
+{
+ off_t off;
+
+ if((off = ftello(stdout)) < 0)
+ return FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED;
+
+ *absolute_byte_offset = off;
+ return FLAC__STREAM_ENCODER_TELL_STATUS_OK;
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: %s [-b bitspersample] [-c channels] [-l compresslevel] [-r sfreq] [-P padding] [-T field=value]\n", argv0);
+ exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int i, n, nm, r, be, bits, chan, level, sfreq;
+ FLAC__StreamMetadata_VorbisComment_Entry vc;
+ FLAC__StreamMetadata *m[2];
+ uint32_t beef = 0xdeadbeef;
+ FLAC__StreamEncoder *enc;
+ FLAC__int32 *buf;
+ int16_t *x;
+
+ be = *((uint8_t*)&beef) == 0xde;
+ m[0] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT);
+ nm = 1;
+
+ bits = 16;
+ chan = 2;
+ sfreq = 44100;
+ level = -1;
+ ARGBEGIN{
+ case 'b':
+ bits = atoi(EARGF(usage()));
+ if(bits <= 8 || bits > 32){
+ fprintf(stderr, "bits per sample = %d not supported\n");
+ exit(1);
+ }
+ break;
+ case 'c':
+ chan = atoi(EARGF(usage()));
+ break;
+ case 'l':
+ level = atoi(EARGF(usage()));
+ break;
+ case 's':
+ sfreq = atoi(EARGF(usage()));
+ break;
+ case 'P':
+ m[nm] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING);
+ m[nm++]->length = atoi(EARGF(usage()));
+ break;
+ case 'T':
+ vc.entry = (FLAC__byte*)EARGF(usage());
+ vc.length = strlen((char*)vc.entry);
+ FLAC__metadata_object_vorbiscomment_append_comment(m[0], vc, true);
+ break;
+ default:
+ usage();
+ }ARGEND
+
+ if(argc != 0)
+ usage();
+
+ n = chan * 4096;
+ if((buf = malloc(n*4)) == NULL){
+ fprintf(stderr, "no memory\n");
+ exit(1);
+ }
+ x = (int16_t*)buf + (bits > 16 ? 0 : n);
+
+ if((enc = FLAC__stream_encoder_new()) == NULL){
+ fprintf(stderr, "failed to create encoder\n");
+ exit(1);
+ }
+ FLAC__stream_encoder_set_bits_per_sample(enc, bits);
+ FLAC__stream_encoder_set_channels(enc, chan);
+ FLAC__stream_encoder_set_sample_rate(enc, sfreq);
+ if(level >= 0)
+ FLAC__stream_encoder_set_compression_level(enc, level);
+ if(!FLAC__stream_encoder_set_metadata(enc, m, nm)){
+ fprintf(stderr, "failed to set metadata\n");
+ exit(1);
+ }
+
+ if(FLAC__stream_encoder_init_stream(enc, encwrite, encseek, enctell, NULL, NULL) != FLAC__STREAM_ENCODER_INIT_STATUS_OK){
+ fprintf(stderr, "failed to init the stream\n");
+ exit(1);
+ }
+
+ for(;;){
+ r = fread(x, bits > 16 ? 4 : 2, n, stdin);
+ if(r < 1)
+ break;
+
+ if(bits <= 16){
+ for(i = 0; i < r; i++)
+ buf[i] = be ? x[i]<<8 | x[i]>>8 : x[i];
+ }else if(be){
+ for(i = 0; i < r; i++)
+ buf[i] = buf[i]<<24 | (buf[i]<<8)&0xff0000 | (buf[i]>>8)&0xff00 | buf[i]>>24;
+ }
+
+ if(!FLAC__stream_encoder_process_interleaved(enc, buf, r/chan)){
+ fprintf(stderr, "encoding failed\n");
+ exit(1);
+ }
+ }
+ if(!FLAC__stream_encoder_finish(enc)){
+ fprintf(stderr, "encoding failed\n");
+ exit(1);
+ }
+ FLAC__stream_encoder_delete(enc);
+
+ return 0;
+}
diff --git a/sys/src/cmd/audio/flacenc/mkfile b/sys/src/cmd/audio/flacenc/mkfile
new file mode 100644
index 000000000..f8bc3a111
--- /dev/null
+++ b/sys/src/cmd/audio/flacenc/mkfile
@@ -0,0 +1,21 @@
+</$objtype/mkfile
+<../config
+
+TARGET=flacenc
+
+CC=pcc
+CFLAGS=-I. -I../libFLAC -I../libFLAC/FLAC -D_POSIX_SOURCE -D_BSD_EXTENSION -DPlan9 -c
+
+%.$O: %.c
+ $CC $CFLAGS -c $stem.c
+
+$O.%: %.$O ../libFLAC/libFLAC.a$O
+ $CC -o $target $prereq
+
+all:V: $O.$TARGET
+
+clean:V:
+ rm -f *.[$OS] [$OS].$TARGET
+
+install:V: $O.$TARGET
+ cp $O.$TARGET $BIN/$TARGET
diff --git a/sys/src/cmd/audio/mkfile b/sys/src/cmd/audio/mkfile
index abc209502..0a9317aac 100644
--- a/sys/src/cmd/audio/mkfile
+++ b/sys/src/cmd/audio/mkfile
@@ -1,7 +1,7 @@
</$objtype/mkfile
LIBS=libogg libvorbis libFLAC
-PROGS=pcmconv oggdec oggenc mp3dec mp3enc flacdec wavdec sundec mixfs
+PROGS=pcmconv oggdec oggenc mp3dec mp3enc flacdec flacenc wavdec sundec mixfs
#libs must be made first
DIRS=$LIBS $PROGS