2022-04-09 16:13:41 +01:00
|
|
|
/*
|
|
|
|
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 {
|
2022-04-09 18:14:30 +01:00
|
|
|
cmd := exec.Command("ffmpeg", "-i", *inputFile, "-ar", "16000", *outputFile)
|
2022-04-09 16:13:41 +01:00
|
|
|
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()
|
|
|
|
|
2022-09-05 16:09:06 +01:00
|
|
|
// // 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()
|
2022-04-09 16:13:41 +01:00
|
|
|
|
|
|
|
// // 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
|
2022-09-05 16:09:06 +01:00
|
|
|
// } //
|