Initial commit

This commit is contained in:
Sameer Rahmani 2022-04-09 16:13:41 +01:00
commit b1f2020eaf
8 changed files with 571 additions and 0 deletions

8
.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
*~
build/
coqui/
.venv/
.env
nc.tar.xz
*.ogg
*.wav

154
builder Executable file
View File

@ -0,0 +1,154 @@
#! /bin/bash
# Orion bot
#
# Copyright (c) 2022 Sameer Rahmani <lxsameer@gnu.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, version 2.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# -----------------------------------------------------------------------------
# Commentary
# -----------------------------------------------------------------------------
# This is the builder script for the Orion project. It makes it easier to
# interact with the build system
#
# In order to define a subcommand all you need to do is to define a function
# with the following syntax:
#
# function subcommand-name() { ## DESCRIPTION
# .. subcommand body ..
# }
#
# Make sure to provid one line of DESCRIPTION for the subcommand and use two "#"
# characters to start the description following by a space. Otherwise, your
# subcommand won't be registered
set -e
# -----------------------------------------------------------------------------
# Vars & Config
# -----------------------------------------------------------------------------
command=$1
VERSION="0.1.0"
# Change the url to point to the stt native client of your platform
STT_BINARY=https://github.com/coqui-ai/STT/releases/download/v1.3.0/native_client.tflite.Linux.tar.xz
MODEL=https://coqui.gateway.scarf.sh/english/coqui/v1.0.0-huge-vocab/model.tflite
SCORER=https://coqui.gateway.scarf.sh/english/coqui/v1.0.0-huge-vocab/huge-vocabulary.scorer
ME=$(cd "$(dirname "$0")/." >/dev/null 2>&1 ; pwd -P)
export CGO_LDFLAGS=-L$ME/coqui/
export CGO_CXXFLAGS=-I$ME/coqui/
export LD_LIBRARY_PATH=$ME/coqui/:$LD_LIBRARY_PATH
# The `builder` script is supposed to be run from the
# root of the source tree
ROOT_DIR=$ME
BUILD_DIR=$ROOT_DIR/build
default_model="$ME/models/default.tflite"
default_scorer="$ME/models/default.scorer"
# -----------------------------------------------------------------------------
# Helper functions
# -----------------------------------------------------------------------------
function fn-names() {
grep -E '^function [0-9a-zA-Z_-]+\(\) \{ ## .*$$' "$0" | sed 's/^function \([a-zA-Z0-9_-]*\)() { ## \(.*\)/\1/'
}
function info() {
if [ "$1" ]
then
echo -e "[\033[01;32mINFO\033[00m]: $1"
fi
}
function error() {
if [ "$1" ]
then
echo -e "[\033[01;31mERR\033[00m]: $1"
fi
}
function warn() {
if [ "$1" ]
then
echo -e "[\033[01;33mWARN\033[00m]: $1"
fi
}
# -----------------------------------------------------------------------------
# Subcomaands
# -----------------------------------------------------------------------------
function setup() { ## Setup the working directory and make it ready for development
info "Creating the virtual env..."
virtualenv "$ME/.venv"
# shellcheck source=.venv/bin/activate
. "$ME/.venv/bin/activate"
info "Intalling tflite runtime..."
pip3 install --extra-index-url https://google-coral.github.io/py-repo/ tflite_runtime
info "Downloding STT..."
wget $STT_BINARY -O nc.tar.xz
mkdir -p "$ME/coqui"
tar -Jxvf nc.tar.xz -C "$ME/coqui"
info "Installing coqui go binding..."
go get -u github.com/asticode/go-asticoqui/...
go mod download
info "Downloading the model..."
wget "$MODEL" -O "$default_model$ME/models/default.tflite"
info "Downloading the scorer..."
wget "$SCORER" -O "$default_scorer"
deactivate
}
function run() { ## Setup the working directory and make it ready for development
# shellcheck source=.venv/bin/activate
. "$ME/.venv/bin/activate"
go run orion.go -model "$default_model" -scorer "$default_scorer" "$@"
deactivate
}
function help() { ## Print out this help message
echo "Commands:"
grep -E '^function [a-zA-Z0-9_-]+\(\) \{ ## .*$$' "$0" | \
sort | \
sed 's/^function \([a-zA-Z0-9_-]*\)() { ## \(.*\)/\1:\2/' | \
awk 'BEGIN {FS=":"}; {printf "\033[36m%-30s\033[0m %s\n", $1, $2}'
}
# -----------------------------------------------------------------------------
# Main logic
# -----------------------------------------------------------------------------
echo -e "\nOrion Version $VERSION"
echo -e "\nCopyright (C) 2022 Sameer Rahmani <lxsameer@gnu.org>"
echo -e "Orion comes with ABSOLUTELY NO WARRANTY;"
echo -e "This is free software, and you are welcome"
echo -e "to redistribute it under certain conditions;"
echo -e "for details take a look at the LICENSE file.\n"
# Find the subcommand in the functions and run we find it.
for fn in $(fn-names); do
if [[ $fn == "$command" ]]; then
eval "$fn" "${@:2}"
exit $?
fi
done
# If we couldn't find the command print out the help message
help

12
go.mod Normal file
View File

@ -0,0 +1,12 @@
module lxsameer.com/go/orion
go 1.17
require (
github.com/asticode/go-asticoqui v0.1.0 // indirect
github.com/cryptix/wav v0.0.0-20180415113528-8bdace674401 // indirect
github.com/joho/godotenv v1.4.0 // indirect
github.com/krig/go-sox v0.0.0-20180617124112-7d2f8ae31981 // indirect
gopkg.in/hraban/opus.v2 v2.0.0-20220302220929-eeacdbcb92d0 // indirect
gopkg.in/telebot.v3 v3.0.0 // indirect
)

58
go.sum Normal file
View File

@ -0,0 +1,58 @@
github.com/asticode/go-asticoqui v0.1.0 h1:vxdDaFIfq04U0oQXJ7z1z+HC/i1/qBf+a0y4q+azBsY=
github.com/asticode/go-asticoqui v0.1.0/go.mod h1:HuUAasCpAyPjOQSqoY92VeBMYLkQ/Hu7Ij3aOhQrwlk=
github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927/go.mod h1:h/aW8ynjgkuj+NQRlZcDbAbM1ORAbXjXX77sX7T289U=
github.com/cryptix/wav v0.0.0-20180415113528-8bdace674401 h1:rZ+OHHkwlkYALTEd6AYXSL92K/SEc4fkz+TfweIwu6A=
github.com/cryptix/wav v0.0.0-20180415113528-8bdace674401/go.mod h1:knK8fd+KPlGGqSUWogv1DQzGTwnfUvAi0cIoWyOG7+U=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/go-audio/audio v1.0.0 h1:zS9vebldgbQqktK4H0lUqWrG8P0NxCJVqcj7ZpNnwd4=
github.com/go-audio/audio v1.0.0/go.mod h1:6uAu0+H2lHkwdGsAY+j2wHPNPpPoeg5AaEFh9FlA+Zs=
github.com/go-audio/riff v1.0.0 h1:d8iCGbDvox9BfLagY94fBynxSPHO80LmZCaOsmKxokA=
github.com/go-audio/riff v1.0.0/go.mod h1:l3cQwc85y79NQFCRB7TiPoNiaijp6q8Z0Uv38rVG498=
github.com/go-audio/wav v1.0.0 h1:WdSGLhtyud6bof6XHL28xKeCQRzCV06pOFo3LZsFdyE=
github.com/go-audio/wav v1.0.0/go.mod h1:3yoReyQOsiARkvPl3ERCi8JFjihzG6WhjYpZCf5zAWE=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
github.com/goccy/go-yaml v1.9.5/go.mod h1:U/jl18uSupI5rdI2jmuCswEA2htH9eXfferR3KfscvA=
github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg=
github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/krig/go-sox v0.0.0-20180617124112-7d2f8ae31981 h1:ir4NRMjkkSP63kAOiFDTQN3dcs0o6c0f1cfpe9V8JT0=
github.com/krig/go-sox v0.0.0-20180617124112-7d2f8ae31981/go.mod h1:0uPmTzngejep+JBRxvlmijKKMexuskpMCzWFp+oFzc4=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/hraban/opus.v2 v2.0.0-20220302220929-eeacdbcb92d0 h1:B8lK1KhYrE4H3urNYBAL/UquYftW65IHPY8JP3gpZ4M=
gopkg.in/hraban/opus.v2 v2.0.0-20220302220929-eeacdbcb92d0/go.mod h1:/L5E7a21VWl8DeuCPKxQBdVG5cy+L0MRZ08B1wnqt7g=
gopkg.in/telebot.v3 v3.0.0 h1:UgHIiE/RdjoDi6nf4xACM7PU3TqiPVV9vvTydCEnrTo=
gopkg.in/telebot.v3 v3.0.0/go.mod h1:7rExV8/0mDDNu9epSrDm/8j22KLaActH1Tbee6YjzWg=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

84
main.go Normal file
View File

@ -0,0 +1,84 @@
package main
import (
"fmt"
"log"
"os"
"time"
"github.com/joho/godotenv"
tele "gopkg.in/telebot.v3"
)
const user = "lxsameer"
const version = "0.1.0"
func main1() {
err := godotenv.Load(".env")
if err != nil {
log.Fatal(err)
return
}
pref := tele.Settings{
Token: os.Getenv("BOT_TOKEN"),
Poller: &tele.LongPoller{Timeout: 10 * time.Second},
}
b, err := tele.NewBot(pref)
if err != nil {
log.Fatal(err)
return
}
b.Handle(tele.OnText, func(c tele.Context) error {
me := c.Sender().Username
if (me != user) {
return c.Send("Get lost!")
}
return c.Send("Get lost!")
})
b.Handle("/version", func(c tele.Context) error {
me := c.Sender().Username
if (me != user) {
return c.Send("Get lost!")
}
return c.Send(version)
})
b.Handle(tele.OnVoice, func(c tele.Context) error {
me := c.Sender().Username
if (me != user) {
return c.Send("Get lost!")
}
fmt.Println("Got a voice!")
audio := c.Message().Voice.File
time := c.Message().Time().Format("2006-01-02_15:04:05")
c.Bot().Download(&audio, time + ".ogg")
fmt.Printf("Got ahthnthnt voice!\n")
// _, err = b.FileReader.Read(content)
// if (err != nil) {
// fmt.Printf("Error: %s\n", err)
// return c.Send("Error!")
// }
// f, err := os.Create("/tmp/f.mp3")
// if (err != nil) {
// fmt.Printf("Error: %s\n", err)
// return c.Send("Error!")
// }
// defer f.Close()
// f.Write(content)
fmt.Println("user:", me)
return c.Send("Got it!")
})
b.Start()
}

58
orion.go Normal file
View File

@ -0,0 +1,58 @@
/*
Orion --- Speech to text bot
Copyright (c) 2022 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package main
import (
"os"
"flag"
"log"
"fmt"
"lxsameer.com/go/orion/pkg/core"
)
var model = flag.String("model", "", "Path to the model (protocol buffer binary file)")
var scorer = flag.String("scorer", "", "Path to the external scorer")
var owner = flag.String("owner", "", "Telegram user id that is allowed to use this bot")
func main() {
flag.Parse()
log.SetFlags(0)
if *model == "" {
// In case of error print error and print usage
// This can also be done by passing -h or --help flags
fmt.Fprintf(flag.CommandLine.Output(), "Usage of %s:\n", os.Args[0])
flag.PrintDefaults()
return
}
// // Initialize Coqui
// m, err := asticoqui.New(*model)
// if err != nil {
// log.Fatal("Failed initializing model: ", err)
// }
// defer m.Close()
a1 := "/home/lxsameer/src/orion/2022-04-09_11:48:57.ogg"
a2 := "/home/lxsameer/src/orion/blah.wav"
err := core.ConvertOggtoWav(&a1, &a2)
if err != nil {
log.Fatal(err)
return
}
log.Println("done!")
}

185
pkg/core/converter.go Normal file
View File

@ -0,0 +1,185 @@
/*
Orion --- Speech to text bot
Copyright (c) 2022 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package core
import (
"os/exec"
)
func ConvertOggtoWav(inputFile *string, outputFile *string) error {
cmd := exec.Command("ffmpeg", "-i", *inputFile, *outputFile)
if err := cmd.Run(); err != nil {
return err
}
return nil
}
// =============================
// Since sox doesn't support Opus and telegram uses opus format, i've
// tried to convert opus to wav but it didn't go well and since it's
// a personal project and I don't want to spend much time on it, I've
// decided to use ffmpeg but I'm keeping my effort here. Maybe in the
// future I spend more time on it.
// func ConvertOpusToWav(inputFile *string, outputFile *string) error {
// channels := 1
// f, err := os.Open(*inputFile)
// if err != nil {
// return err
// }
// defer f.Close()
// wavOut, err := os.Create(*outputFile)
// if err != nil {
// return err
// }
// defer wavOut.Close()
// out := wav.File{
// Channels: 1,
// SampleRate: rate,
// SignificantBits: bits,
// }
// writer, err := out.NewWriter(wavOut)
// if err != nil {
// return err
// }
// defer writer.Close()
// s, err := opus.NewStream(f)
// if err != nil {
// return err
// }
// defer s.Close()
// pcmbuf := make([]int16, )
// for {
// n, err := s.Read(pcmbuf)
// if err == io.EOF {
// break
// } else if err != nil {
// return err
// }
// pcm := pcmbuf[:n*channels]
// buf := new(bytes.Buffer)
// err = binary.Write(buf, binary.LittleEndian, pcm)
// if err != nil {
// return err
// }
// writer.WriteSample(buf.Bytes())
// // send pcm to audio device here, or write to a .wav file
// }
// return nil
// // sampleRate := 16000
// // frameSizeMs := 60
// // frameSize := channels * frameSizeMs * sampleRate / 1000
// // dec, err := opus.NewDecoder(sampleRate, channels)
// // if err != nil {
// // return nil, err
// // }
// // in, err := os.Open(*inputFile)
// // if err != nil {
// // return nil, err
// // }
// // defer in.Close()
// // data, err := ioutil.ReadFile(*inputFile)
// // if err != nil {
// // return nil, err
// // }
// // pcm := make([]int16, int(frameSize))
// // n, err := dec.Decode(data, pcm)
// // if err != nil {
// // return nil, err
// // }
// // // To get all samples (interleaved if multiple channels):
// // pcm = pcm[:n*channels] // only necessary if you didn't know the right frame size
// // return pcm, nil
// // // buf := new(bytes.Buffer)
// // // err = binary.Write(buf, binary.LittleEndian, pcm)
// // // if(err != nil) {
// // // return nil, err
// // // }
// // // return buf.Bytes(), nil
// }
// func ConvertToWav(inputFile *string, outputFile *string) error {
// if !sox.Init() {
// return fmt.Errorf("failed to initialize SoX")
// }
// defer sox.Quit()
// // Open the input file (with default parameters)
// in := sox.OpenRead(*inputFile)
// if in == nil {
// return fmt.Errorf("failed to open input ogg file")
// }
// // Close the file before exiting
// defer in.Release()
// out := sox.OpenWrite(*outputFile, in.Signal(), nil, "alsa")
// if out == nil {
// out = sox.OpenWrite("default", in.Signal(), nil, "pulseaudio")
// if out == nil {
// return fmt.Errorf("failed to open output device")
// }
// }
// // Close the output device before exiting
// defer out.Release()
// // Create an effects chain: Some effects need to know about the
// // input or output encoding so we provide that information here.
// chain := sox.CreateEffectsChain(in.Encoding(), out.Encoding())
// // Make sure to clean up!
// defer chain.Release()
// // The first effect in the effect chain must be something that can
// // source samples; in this case, we use the built-in handler that
// // inputs data from an audio file.
// e := sox.CreateEffect(sox.FindEffect("input"))
// e.Options(in)
// // This becomes the first "effect" in the chain
// chain.Add(e, in.Signal(), in.Signal())
// e.Release()
// // // Create the `rate' effect, to set the samplerate
// // e = sox.CreateEffect(sox.FindEffect("rate"))
// // e.Options(16000)
// // chain.Add(e, in.Signal(), in.Signal())
// // e.Release()
// // The last effect in the effect chain must be something that only consumes
// // samples; in this case, we use the built-in handler that outputs data.
// e = sox.CreateEffect(sox.FindEffect("output"))
// e.Options(out)
// chain.Add(e, in.Signal(), in.Signal())
// e.Release()
// // Flow samples through the effects processing chain until EOF is reached.
// chain.Flow()
// return nil
// }

12
pkg/core/core.go Normal file
View File

@ -0,0 +1,12 @@
package core
// import (
// "flag"
// "fmt"
// "io"
// "log"
// "os"
// "github.com/asticode/go-asticoqui"
// "github.com/cryptix/wav"
// )