/* Orion --- Speech to text bot Copyright (c) 2022 Sameer Rahmani 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 . */ package core import ( "os/exec" ) func ConvertOggtoWav(inputFile *string, outputFile *string) error { cmd := exec.Command("ffmpeg", "-i", *inputFile, "-ar", "16000", *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 // }