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
+15.7k Golang : Get sub string example
+11.7k Golang : Sort and reverse sort a slice of runes
+5.4k Fix fatal error: evacuation not done in time problem
+16k Golang : Test floating point numbers not-a-number and infinite example
+11.3k Golang : Display a text file line by line with line number example
+5.4k Golang : ROT32768 (rotate by 0x80) UTF-8 strings example
+18.2k Golang : Send email with attachment
+10.7k Golang : Web routing/multiplex example
+42.7k Golang : Get hardware information such as disk, memory and CPU usage
+13.3k Golang : Query string with space symbol %20 in between
+13.7k Golang : concatenate(combine) strings
+32.3k Golang : Regular Expression for alphanumeric and underscore