Golang : Record voice(audio) from microphone to .WAV file
Problem:
You need to activate your microphone, record your voice and save the data into a .wav
file from command line. How to do that?
Solution:
The code example below is combination of PortAudio (https://github.com/gordonklaus/portaudio/blob/master/examples/record.go) and Golang wave file reader/writer (https://github.com/zenwerk/go-wave/blob/master/example/writing.go).
What it does is to activate your default microphone and start recording. Encode the data([]byte) to the wave.Write() function and save to a given .wav
file.
Here you go!
record2wave.go
package main
/*
#include <stdio.h>
#include <unistd.h>
#include <termios.h>
char getch(){
char ch = 0;
struct termios old = {0};
fflush(stdout);
if( tcgetattr(0, &old) < 0 ) perror("tcsetattr()");
old.c_lflag &= ~ICANON;
old.c_lflag &= ~ECHO;
old.c_cc[VMIN] = 1;
old.c_cc[VTIME] = 0;
if( tcsetattr(0, TCSANOW, &old) < 0 ) perror("tcsetattr ICANON");
if( read(0, &ch,1) < 0 ) perror("read()");
old.c_lflag |= ICANON;
old.c_lflag |= ECHO;
if(tcsetattr(0, TCSADRAIN, &old) < 0) perror("tcsetattr ~ICANON");
return ch;
}
*/
import "C"
// stackoverflow.com/questions/14094190/golang-function-similar-to-getchar
import (
"fmt"
"github.com/gordonklaus/portaudio"
wave "github.com/zenwerk/go-wave"
"math/rand"
"os"
"strings"
"time"
)
func errCheck(err error) {
if err != nil {
panic(err)
}
}
func main() {
if len(os.Args) != 2 {
fmt.Printf("Usage : %s <audiofilename.wav>\n", os.Args[0])
os.Exit(0)
}
audioFileName := os.Args[1]
fmt.Println("Recording. Press ESC to quit.")
if !strings.HasSuffix(audioFileName, ".wav") {
audioFileName += ".wav"
}
waveFile, err := os.Create(audioFileName)
errCheck(err)
// www.people.csail.mit.edu/hubert/pyaudio/ - under the Record tab
inputChannels := 1
outputChannels := 0
sampleRate := 44100
framesPerBuffer := make([]byte, 64)
// init PortAudio
portaudio.Initialize()
//defer portaudio.Terminate()
stream, err := portaudio.OpenDefaultStream(inputChannels, outputChannels, float64(sampleRate), len(framesPerBuffer), framesPerBuffer)
errCheck(err)
//defer stream.Close()
// setup Wave file writer
param := wave.WriterParam{
Out: waveFile,
Channel: inputChannels,
SampleRate: sampleRate,
BitsPerSample: 8, // if 16, change to WriteSample16()
}
waveWriter, err := wave.NewWriter(param)
errCheck(err)
//defer waveWriter.Close()
go func() {
key := C.getch()
fmt.Println()
fmt.Println("Cleaning up ...")
if key == 27 {
// better to control
// how we close then relying on defer
waveWriter.Close()
stream.Close()
portaudio.Terminate()
fmt.Println("Play", audioFileName, "with a audio player to hear the result.")
os.Exit(0)
}
}()
// recording in progress ticker. From good old DOS days.
ticker := []string{
"-",
"\\",
"/",
"|",
}
rand.Seed(time.Now().UnixNano())
// start reading from microphone
errCheck(stream.Start())
for {
errCheck(stream.Read())
fmt.Printf("\rRecording is live now. Say something to your microphone! [%v]", ticker[rand.Intn(len(ticker)-1)])
// write to wave file
_, err := waveWriter.Write([]byte(framesPerBuffer)) // WriteSample16 for 16 bits
errCheck(err)
}
errCheck(stream.Stop())
}
References:
See also : Golang : Save webcamera frames to video file
By Adam Ng
IF you gain some knowledge or the information here solved your programming problem. Please consider donating to the less fortunate or some charities that you like. Apart from donation, planting trees, volunteering or reducing your carbon footprint will be great too.
Advertisement
Tutorials
+12.7k Golang : How to pass map to html template and access the map's elements
+4.2k Golang : Calculate half life decay example
+5.2k Linux/Unix : Commands that you need to be careful about
+16.4k Golang : Read data from config file and assign to variables
+6.2k Golang : Check if one string(rune) is permutation of another string(rune)
+3.6k Linux/MacOSX : Search and delete files by extension
+11.2k Golang : Search and extract certain XML data example
+8.6k Javascript : Read/parse JSON data from HTTP response
+4.6k Python : Print unicode escape characters and string
+35.3k Golang : Convert(cast) int64 to string
+4.3k Golang : The Tao of importing package
+6.3k Golang : Calculate how many weeks left to go in a given year