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
+17.7k Golang : Calculate entire request body length during run time
+4.8k Golang : Denco multiplexer example
+7.6k Golang : Executing and evaluating nested loop in html template
+16k Golang : How to save log messages to file?
+5.9k Golang : Normalize email to prevent multiple signups example
+11.4k Golang : Exit, terminating or aborting a program
+8.5k Golang : Format strings to SEO friendly URL example
+8.3k Golang : Find correlation coefficient example
+9.9k Golang : How to determine a prime number?
+81.4k Golang : How to convert character to ASCII and back
+12.9k Golang : Convert IP version 6 address to integer or decimal number
+11.2k Golang : Listen and Serve on sub domain example