code: plan9front

Download patch

ref: ce82f6750c5d98968259b80614643ed63b972ea3
parent: 10237a22f189d304668283fb82870b36144d4d1b
author: Sigrid <ftrvxmtrx@gmail.com>
date: Mon Jan 11 10:45:12 EST 2021

audio/flacenc

diff: cannot open b/sys/src/cmd/audio/flacenc//null: file does not exist: 'b/sys/src/cmd/audio/flacenc//null'
--- a/sys/man/1/audio
+++ b/sys/man/1/audio
@@ -1,6 +1,6 @@
 .TH AUDIO 1
 .SH NAME
-mp3dec, mp3enc, oggdec, oggenc, flacdec, sundec, wavdec, pcmconv, mixfs \- decode and encode audio files
+mp3dec, mp3enc, oggdec, oggenc, flacdec, flacenc, sundec, wavdec, pcmconv, mixfs \- decode and encode audio files
 .SH SYNOPSIS
 .B audio/mp3dec
 [
@@ -55,6 +55,27 @@
 ] [
 .I "long or silly options"
 ]
+.br
+.B audio/flacenc
+[
+.B -b
+.I bitspersample
+] [
+.B -c
+.I channels
+] [
+.B -l
+.I compresslevel
+] [
+.B -s
+.I sfreq
+] [
+.B -P
+.I padding
+] [
+.B -T
+.I field=value
+]
 .PP
 .B audio/pcmconv
 [
@@ -107,10 +128,11 @@
 The encoders read PCM on standard input and produce compressed audio
 on standard output.
 .PP
-.I Oggenc
+.I Flacenc,
+.I oggenc
 and
 .I mp3enc
-produce OGG Vorbis and MP3 audio. For
+produce FLAC, OGG Vorbis and MP3 audio. For
 .I mp3enc,
 the MP3 file will use `constant bit-rate' (CBR) encoding by default, 
 but that can be changed via
@@ -120,11 +142,13 @@
 .BR -v
 (variable bitrate, VBR).
 .PP
-.I Oggenc
-accepts raw PCM in the same byte order as
+.I Flacenc
+and
+.I oggenc
+accept raw PCM in the same byte order as
 .B /dev/audio
 (little-endian),
-t
+while
 .I mp3enc -r
 expects big-endian.
 .SS Encoding options
@@ -380,3 +404,5 @@
 first appeared in 9front (December, 2012).
 .I Mixfs
 first appeared in 9front (December, 2013).
+.I Flacenc
+first appeared in 9front (January, 2020).
--- /dev/null
+++ b/sys/src/cmd/audio/flacenc/flacenc.c
@@ -1,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;
+}
--- /dev/null
+++ b/sys/src/cmd/audio/flacenc/mkfile
@@ -1,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
--- 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