Example #1
0
func newStereoSine(freqL, freqR, sampleRate float64) *stereoSine {
	s := &stereoSine{nil, freqL / sampleRate, 0, freqR / sampleRate, 0}
	var err error
	s.Stream, err = portaudio.OpenDefaultStream(0, 2, sampleRate, 0, s.processAudio)
	chk(err)
	return s
}
Example #2
0
func main() {
	w := &window{voices: map[int]*sineVoice{}}
	p := audio.Params{SampleRate: 96000}
	audio.Init(w, p)

	portaudio.Initialize()
	defer portaudio.Terminate()
	s, err := portaudio.OpenDefaultStream(0, 1, p.SampleRate, 64, w.processAudio)
	if err != nil {
		fmt.Println(err)
		return
	}
	if err := s.Start(); err != nil {
		fmt.Println(err)
		return
	}
	defer s.Stop()

	if err := gui.Run(func() {
		gui.NewWindow(w, "beep", func(win *gui.Window) {
			w.Window = win
			gui.SetKeyFocus(w)
		})
	}); err != nil {
		fmt.Println(err)
	}
}
Example #3
0
func (self *Server) openAudioStream(in []int32) (*portaudio.Stream, error) {
	var device *portaudio.DeviceInfo
	var stream *portaudio.Stream
	var err error

	if self.Config.Input != nil {
		devices, err := portaudio.Devices()
		for _, deviceInfo := range devices {
			if deviceInfo.Name == self.Config.Input.Name {
				device = deviceInfo
				break
			}
		}

		if device != nil {
			log.Printf("Use %v", device)
			stream, err = portaudio.OpenStream(portaudio.StreamParameters{
				Input: portaudio.StreamDeviceParameters{
					Device:   device,
					Channels: 2,
					Latency:  device.DefaultHighInputLatency,
				},
				Output: portaudio.StreamDeviceParameters{
					Device:   nil,
					Channels: 0,
					Latency:  0,
				},
				SampleRate:      self.Config.Input.SampleRate,
				FramesPerBuffer: len(in),
				Flags:           portaudio.NoFlag,
			}, in)
			if err != nil {
				return nil, err
			}
		} else {
			log.Printf("No matched devices: (required: '%s')", self.Config.Input.Name)
			for _, deviceInfo := range devices {
				log.Printf("Found Device... %s %.1f", deviceInfo.Name, deviceInfo.DefaultSampleRate)
			}
			log.Printf("Fallback to default input device")
		}
	}

	if device == nil {
		device, err = portaudio.DefaultInputDevice()
		log.Printf("Use %v", device)
		if err != nil {
			return nil, err
		}

		stream, err = portaudio.OpenDefaultStream(2, 0, device.DefaultSampleRate, len(in), in)
		if err != nil {
			return nil, err
		}
	}

	return stream, nil
}
Example #4
0
File: port.go Project: shazow/mog
func get(sampleRate, channels int) (Output, error) {
	o := &port{
		ch: make(chan []float32),
	}
	var err error
	o.st, err = portaudio.OpenDefaultStream(0, channels, float64(sampleRate), 1024, o.Fetch)
	if err != nil {
		return nil, err
	}
	return o, nil
}
Example #5
0
File: stt.go Project: kladd/stt
// Slightly modified exact copy of the portaudio example
func record(f *os.File, timer <-chan time.Time) {
	// form chunk
	_, _ = f.WriteString("FORM")
	binary.Write(f, binary.BigEndian, int32(0))
	_, _ = f.WriteString("AIFF")

	// common chunk
	_, _ = f.WriteString("COMM")
	binary.Write(f, binary.BigEndian, int32(18))
	binary.Write(f, binary.BigEndian, int16(1))
	binary.Write(f, binary.BigEndian, int32(0))
	binary.Write(f, binary.BigEndian, int16(32))
	_, _ = f.Write([]byte{0x40, 0x0e, 0xac, 0x44, 0, 0, 0, 0, 0, 0}) //80-bit sample rate 44100

	// sound chunk
	_, _ = f.WriteString("SSND")
	binary.Write(f, binary.BigEndian, int32(0))
	binary.Write(f, binary.BigEndian, int32(0))
	binary.Write(f, binary.BigEndian, int32(0))
	nSamples := 0
	defer func() {
		// fill in missing sizes
		totalBytes := 4 + 8 + 18 + 8 + 8 + 4*nSamples
		_, _ = f.Seek(4, 0)
		binary.Write(f, binary.BigEndian, int32(totalBytes))
		_, _ = f.Seek(22, 0)
		binary.Write(f, binary.BigEndian, int32(nSamples))
		_, _ = f.Seek(42, 0)
		binary.Write(f, binary.BigEndian, int32(4*nSamples+8))
		f.Close()
	}()

	portaudio.Initialize()
	defer portaudio.Terminate()
	in := make([]int32, 64)
	stream, _ := portaudio.OpenDefaultStream(1, 0, 44100, len(in), in)
	defer stream.Close()

	stream.Start()
	defer stream.Stop()

	for {
		stream.Read()
		binary.Write(f, binary.BigEndian, in)
		nSamples += len(in)
		select {
		case <-timer:
			return
		default:
		}
	}
}
Example #6
0
func (a *app) OnInit() {
	var err error
	a.r, err = os.Open(*in)
	if err != nil {
		log.Fatalf("Unable to open file '%s': %s", *in, err)
	}
	var wm webm.WebM
	a.reader, err = webm.Parse(a.r, &wm)
	if err != nil {
		log.Fatal("Unable to parse file: ", err)
	}
	a.duration = wm.GetDuration()
	var vtrack *webm.TrackEntry
	if !*justaudio {
		vtrack = wm.FindFirstVideoTrack()
	}
	var vstream *webm.Stream
	if vtrack != nil {
		vstream = webm.NewStream(vtrack)
		a.fduration = vtrack.GetDefaultDuration()
		a.vchan = vstream.VideoChannel()
	}
	var atrack *webm.TrackEntry
	if !*justvideo {
		atrack = wm.FindFirstAudioTrack()
	}
	var astream *webm.Stream
	if atrack != nil {
		astream = webm.NewStream(atrack)
	}
	splitter := webm.NewSplitter(a.reader.Chan)
	splitter.Split(astream, vstream)

	a.steps = uint(0xffffffff)
	if a.vchan != nil {
		a.img = <-a.vchan
		a.pimg = a.img
	}

	if atrack != nil {
		channels := int(atrack.Audio.Channels)
		a.aw = &AudioWriter{ch: astream.AudioChannel(),
			channels: channels, active: true}
		chk(portaudio.Initialize())
		a.pastream, err = portaudio.OpenDefaultStream(0, channels,
			atrack.Audio.SamplingFrequency, 0, a.aw.processAudio)
		chk(err)
		chk(a.pastream.Start())
	}
}
Example #7
0
func main() {
	flag.Parse()
	if *random {
		*seed = time.Now().UnixNano()
		fmt.Println("seed =", *seed)
	}
	if *seed != math.MinInt64 {
		*random = true
	}
	rand.Seed(*seed)

	portaudio.Initialize()
	defer portaudio.Terminate()

	p := audio.Params{SampleRate: 48000}

	m := audio.MultiVoice{}
	audio.Init(&m, p)
	// for _, x := range [][2]float64{{1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1}, {3, 2}, {4, 3}, {5, 4}, {7, 4}, {6, 5}, {7, 5}, {8, 5}, {9, 5}} {
	for xy := 1; xy <= 60; xy++ {
		for x := 2; x <= int(math.Sqrt(float64(xy))); x++ {
			if y := xy / x; x*y == xy && relPrime(x, y) {
				x, y, xy := float64(x), float64(y), float64(xy)
				c := math.Exp(-xy * math.Log2(y/x) / 12)
				f := y / x
				phase := 0.0
				if *random {
					phase = rand.Float64()
				}
				m.Add(newSineBeat(.5*c, 128*f, 1/xy, phase, .1/f))
			}
		}
	}

	s, err := portaudio.OpenDefaultStream(0, 1, p.SampleRate, 512, func(out []float32) {
		for i := range out {
			out[i] = float32(audio.Saturate(m.Sing()))
		}
	})
	if err != nil {
		panic(err)
	}
	s.Start()
	fmt.Println("Press Enter to stop.")
	fmt.Scanln()
	s.Stop()
}
Example #8
0
func startPlaying(v Voice, c PlayControl) error {
	const sampleRate = 96000
	Init(v, Params{SampleRate: sampleRate})
	var err error
	stream, err = portaudio.OpenDefaultStream(0, 1, sampleRate, 1024, func(out []float32) {
		for i := range out {
			out[i] = float32(v.Sing())
		}
		if v.Done() {
			c.Stop()
		}
	})
	if err != nil {
		return err
	}
	return stream.Start()
}
Example #9
0
func (e *Engine) Start() error {
	stream, err := portaudio.OpenDefaultStream(0, 1, waveHz, FrameLength, e.processAudio)
	if err != nil {
		return err
	}
	errc := make(chan error)
	go func() {
		err = stream.Start()
		errc <- err
		if err != nil {
			return
		}
		<-e.done
		err = stream.Stop()
		if err == nil {
			err = stream.Close()
		}
		e.done <- err
	}()
	return <-errc
}
Example #10
0
func (pa *portAudio) player() {
	out := make([]int16, 2048*2)

	stream, err := portaudio.OpenDefaultStream(
		0,
		2,     // audio.format.Channels,
		44100, // float64(audio.format.SampleRate),
		len(out),
		&out,
	)
	if err != nil {
		panic(err)
	}
	defer stream.Close()

	stream.Start()
	defer stream.Stop()

	for {
		// Decode the incoming data which is expected to be 2 channels and
		// delivered as int16 in []byte, hence we need to convert it.

		select {
		case audio := <-pa.buffer:
			if len(audio.frames) != 2048*2*2 {
				// panic("unexpected")
				// don't know if it's a panic or track just ended
				break
			}

			j := 0
			for i := 0; i < len(audio.frames); i += 2 {
				out[j] = int16(audio.frames[i]) | int16(audio.frames[i+1])<<8
				j++
			}

			stream.Write()
		}
	}
}
Example #11
0
func main() {
	if len(os.Args) < 2 {
		fmt.Println("Usage:", os.Args[0], "hostname:port [buffer-duration]")
		os.Exit(1)
		return
	}

	portaudio.Initialize()
	defer portaudio.Terminate()

	addr := os.Args[1]
	bufferStr := "100ms"
	if len(os.Args) > 2 {
		bufferStr = os.Args[2]
	}
	bufferLen, err := time.ParseDuration(bufferStr)
	if err != nil {
		fmt.Printf("Invalid buffer length: %v\n", err)
		return
	}

	conn, err := net.Dial("tcp", addr)
	if err != nil {
		fmt.Println("Error connecting to server:", err)
		return
	}
	defer conn.Close()

	buf := make([]byte, 8)
	_, err = io.ReadFull(conn, buf)
	if err != nil {
		fmt.Println("Error reading headers:", err)
		return
	}

	if buf[0] != 'R' {
		fmt.Printf("Invalid header start: %x\n", buf[0])
		return
	} else if buf[1] == 0 {
		fmt.Println("Server is full")
		return
	} else if buf[1] != 1 {
		fmt.Printf("Unsupported protocol version: %d\n", buf[1])
		return
	}

	flags := buf[2]
	if flags&rawstreamer.EncodingLittleEndian != 0 {
		Endianness = binary.LittleEndian
	} else if flags&rawstreamer.EncodingBigEndian != 0 {
		Endianness = binary.BigEndian
	} else {
		fmt.Println("Encoding endianness not specified!")
		return
	}

	encoding := flags & rawstreamer.EncodingMask

	numBytes := int(buf[3])
	bits := numBytes * 8
	if numBytes < 1 || numBytes > 4 {
		fmt.Printf("Unsupported number of bits: %d\n", bits)
		return
	}
	if encoding == rawstreamer.EncodingFloatingPoint {
		numBytes = 4
		bits = 32
	}

	sampleRate := Endianness.Uint32(buf[4:])
	fmt.Printf("Streaming info: %dHz, ", sampleRate)
	fmt.Printf("%dbit %s, ", bits, rawstreamer.EncodingString[encoding])
	fmt.Printf("%s, %v buffer\n", Endianness.String(), bufferLen)

	bufferSize := sampleRate / 50 // 20ms buffer size

	Buffers = []chan float32{
		make(chan float32, getChannelBufferSize(bufferLen, bufferSize, sampleRate)),
		make(chan float32, getChannelBufferSize(bufferLen, bufferSize, sampleRate)),
	}

	Buffering = int32(getChannelBufferSize(bufferLen, bufferSize, sampleRate))
	LastLeft = 0
	LastRight = 0

	printStatus()

	Stream, err = portaudio.OpenDefaultStream(0, 2, float64(sampleRate), int(bufferSize), processAudio)
	defer Stream.Close()
	err = Stream.Start()
	if err != nil {
		fmt.Println("Failed to start stream:", err)
		return
	}
	defer func() {
		Stream.Stop()
		close(Buffers[0])
		close(Buffers[1])
	}()

	buf = make([]byte, int(bufferSize)*numBytes*2)
	align := 8 % (numBytes * 2)
	if align > 0 {
		// Read in the extra padding
		_, err = io.ReadFull(conn, buf[:(numBytes*2)-align])
		if err != nil {
			fmt.Println("Error reading headers:", err)
			return
		}
	}

	var lastData time.Time
	remainder := 0
	for {
		n := 0
		conn.SetReadDeadline(time.Now().Add(2 * time.Minute))
		n, err = io.ReadAtLeast(conn, buf[remainder:], numBytes*2-remainder)
		if err != nil {
			fmt.Println("Error reading stream:", err)
			return
		}
		n += remainder
		remainder = n % (numBytes * 2)

		for i := 0; i < (n - remainder); i += numBytes * 2 {
			BufferingSync.Lock()

			left := rawstreamer.ReadFloat32(buf[i:i+numBytes], flags, Endianness)
			right := rawstreamer.ReadFloat32(buf[i+numBytes:i+numBytes*2], flags, Endianness)
			if left != 0 || right != 0 {
				lastData = time.Now()
				Buffers[0] <- left
				Buffers[1] <- right
			} else if time.Since(lastData) < 1*time.Minute {
				Buffers[0] <- left
				Buffers[1] <- right
			}
			if atomic.LoadInt32(&Buffering) > 0 && time.Since(lastData) < 1*time.Minute {
				atomic.AddInt32(&Buffering, -1)
			}
			BufferingSync.Unlock()
		}

		copy(buf, buf[n-remainder:n])
	}
}
Example #12
0
func Play(x audio.Voice) {
	var v int
	var v2 *audio.Params
	var v3 interface{}
	var v4 *portaudio.Stream
	var v5 *portaudio.Stream
	var v6 chan struct{}
	var v7 chan struct{}
	var v8 interface{}
	var v9 float64
	var v10 float64
	var v11 int
	var v12 audio.Voice
	var v13 int
	v12 = x
	v8 = x
	portaudio.Initialize()      //;0
	defer portaudio.Terminate() //0;
	var v14 int
	x2 := make(chan struct{}, v14)
	v6 = x2
	v7 = x2
	const x3 = 96000
	v9 = x3
	v10 = x3
	const x4 = 64
	v13 = x4
	v = x4
	x5 := &audio.Params{SampleRate: v10, BufferSize: v13}
	v2 = x5
	v2.Set(v8) //;1
	const x6 = 1
	v11 = x6
	x7 := func(in [][]float32, out [][]float32) {
		var v15 []float32
		var v16 [][]float32
		var v17 bool
		var v18 audio.Audio
		v16 = out
		x8, done := v12.Sing()
		v18 = x8
		v17 = done
		var v19 int
		x9 := &v16[v19]
		v15 = *x9
		for k := range v18 {
			var v20 = &v18[k]
			var v21 int
			var v22 float64
			var v23 float32
			v21 = k
			v22 = *v20
			x10 := (float32)(v22)
			v23 = x10
			v15[v21] = v23
		}
		if v17 {
			var v24 struct{}
			select {
			case v7 <- v24:
			default:
			}
		}
	}
	v3 = x7
	var v25 int
	x11, _ := portaudio.OpenDefaultStream(v25, v11, v9, v, v3) //0;
	v4 = x11
	v5 = x11
	v4.Start() //1;2
	<-v6       //2;3
	v5.Stop()  //3;
}
Example #13
0
//Creates a new engine and populates it with the core functions
func LoadAudio(e *Engine) *Engine {

	e = add(e, "portaudio.init", NewCode("portaudio.init", 0, func(e *Engine, c *Thingy) *Engine {
		portaudio.Initialize()
		return e
	}))

	e = add(e, "portaudio.terminate", NewCode("portaudio.terminate", 0, func(e *Engine, c *Thingy) *Engine {
		defer portaudio.Terminate()
		return e
	}))

	e = add(e, "portaudio.setData", NewCode("setData", 3, func(ne *Engine, c *Thingy) *Engine {
		var posString, buffWrap, valString *Thingy
		posString, ne.dataStack = popStack(ne.dataStack)
		valString, ne.dataStack = popStack(ne.dataStack)
		buffWrap, ne.dataStack = popStack(ne.dataStack)

		var pos, _ = strconv.ParseInt(posString.getSource(), 10, 32)
		var val, _ = strconv.ParseFloat(valString.getSource(), 32)
		out := buffWrap._structVal.([][]float32)
		out[0][pos] = float32(val)

		return ne
	}))

	e = add(e, "portaudio.start", NewCode("portaudio.start", -1, func(e *Engine, c *Thingy) *Engine {
		//AudioCallbackState = e.RunString("CLEARSTACK", "setup audio callback")
		AudioCallbackState = e
		stream, err := portaudio.OpenDefaultStream(0, 2, sampleRate, 0, processAudio)
		chk(err)
		stream.Start()
		chk(err)
		e.dataStack = pushStack(e.dataStack, NewWrapper(stream))
		chk(err)
		return e
	}))

	e = add(e, "portaudio.HostApis", NewCode("portaudio.HostApis", 0, func(e *Engine, c *Thingy) *Engine {
		var tmpl = template.Must(template.New("").Parse(
			`[ {{range .}}
	
	H[ 
		Name                   [ {{.Name}} ]
		{{if .DefaultInputDevice}}DefaultInput   [ {{.DefaultInputDevice.Name}} ] {{end}}
		{{if .DefaultOutputDevice}}DefaultOutput  [ {{.DefaultOutputDevice.Name}} ] {{end}}
		Devices [ {{range .Devices}}
					H[	
						Name                      [ {{.Name}} ]
						MaxInputChannels          [ {{.MaxInputChannels}} ]
						MaxOutputChannels         [ {{.MaxOutputChannels}} ]
						DefaultLowInputLatency    [ {{.DefaultLowInputLatency}} ]
						DefaultLowOutputLatency   [ {{.DefaultLowOutputLatency}} ]
						DefaultHighInputLatency   [  {{.DefaultHighInputLatency}} ]
						DefaultHighOutputLatency  [  {{.DefaultHighOutputLatency}} ]
						DefaultSampleRate         [  {{.DefaultSampleRate}} ]
					]H
				{{end}}
				]
	]H
{{end}}
]`,
		))
		var b bytes.Buffer
		hs, err := portaudio.HostApis()
		chk(err)
		err = tmpl.Execute(&b, hs)
		chk(err)
		s := b.String()
		fmt.Println(s)
		return e
	}))

	return e
}
Example #14
0
// Init starts the audio system, loads sound assets, and starts the sound loop.
func Init() error {
	if err := portaudio.Initialize(); err != nil {
		return err
	}

	log.Printf("PortAudio version: %d %s", portaudio.Version(), portaudio.VersionText())

	var err error
	makeBuffer := func(name string) []int16 {
		if err != nil {
			return nil
		}

		var r io.Reader
		if r, err = asset.Reader(name); err != nil {
			return nil
		}

		var w *wav
		if w, err = decodeWAV(r); err != nil {
			return nil
		}

		log.Printf("%s: %+v", name, w)
		buf := make([]int16, len(w.data)/2)
		for i := 0; i < len(buf); i++ {
			buf[i] = int16(w.data[i*2])
			buf[i] += int16(w.data[i*2+1]) << 8
		}
		return buf
	}

	var soundBuffers [][]int16
	for _, a := range soundAssets {
		soundBuffers = append(soundBuffers, makeBuffer(a))
	}
	if err != nil {
		return err
	}

	soundQueue := make(chan Sound, soundQueueSize)
	Play = func(s Sound) {
		soundQueue <- s
	}

	done := make(chan bool)
	Terminate = func() {
		done <- true
		<-done
		close(done)
		logFatalIfErr("portaudio.Terminate", portaudio.Terminate())
	}

	go func() {
		const (
			numInputChannels  = 0     /* zero input - no recording */
			numOutputChannels = 2     /* stereo output */
			sampleRate        = 44100 /* samples per second */
			intervalMs        = 100
			framesPerBuffer   = sampleRate / 1000.0 * intervalMs /*  len(buf) == numChannels * framesPerBuffer */
			outputBufferSize  = numOutputChannels * framesPerBuffer
		)

		// Temporary buffers to read and write the next audio batch.
		tmpIn := make([]int16, outputBufferSize)
		tmpOut := make([]int16, outputBufferSize)

		// outputRingBuffer is a buffer that the PortAudio callback will read data from,
		// and that we will periodically wake up to write new data to.
		outputRingBuffer := newRingBuffer(outputBufferSize * 10)

		// process is the callback that PortAudio will call when it needs audio data.
		process := func(out []int16) {
			outputRingBuffer.pop(tmpIn)
			for i := 0; i < len(out); i++ {
				out[i] = tmpIn[i]
			}
		}

		stream, err := portaudio.OpenDefaultStream(numInputChannels, numOutputChannels, sampleRate, framesPerBuffer, process)
		logFatalIfErr("portaudio.OpenDefaultStream", err)
		defer func() {
			logFatalIfErr("stream.Close", stream.Close())
		}()

		logFatalIfErr("stream.Start()", stream.Start())
		defer func() {
			// stream.Stop blocks until all samples have been played.
			logFatalIfErr("stream.Stop", stream.Stop())
			done <- true
		}()

		var active [][]int16
		quit := false

	loop:
		for {
			select {
			case <-time.After(intervalMs * time.Millisecond):
				// Play whatever sounds are in the queue at the time.
				n := len(soundQueue)
				for i := 0; i < n; i++ {
					active = append(active, soundBuffers[<-soundQueue])
				}

				// Fill temporary buffer with any active sounds buffers.
				for i := 0; i < len(tmpOut); i++ {
					// Combine active signals together.
					var v int16
					for j := 0; j < len(active); j++ {
						// Remove any buffers if they have no more samples.
						if len(active[j]) == 0 {
							active = append(active[:j], active[j+1:]...)
							j--
							continue
						}
						v += active[j][0]
						active[j] = active[j][1:]
					}
					tmpOut[i] = v
				}
				outputRingBuffer.push(tmpOut...)

				// Only quit waking until there are no more streams to play.
				if quit && len(active) == 0 {
					break loop
				}

			case <-done:
				close(soundQueue) // Prevent any new sounds from being scheduled.
				quit = true
			}
		}
	}()

	return nil
}
Example #15
0
func main() {
	if len(os.Args) < 2 {
		fmt.Println("missing required argument:  input file name")
		return
	}
	fmt.Println("Playing.  Press Ctrl-C to stop.")

	sig := make(chan os.Signal, 1)
	signal.Notify(sig, os.Interrupt, os.Kill)

	fileName := os.Args[1]
	f, err := os.Open(fileName)
	chk(err)
	defer f.Close()

	id, data, err := readChunk(f)
	chk(err)
	if id.String() != "FORM" {
		fmt.Println("bad file format")
		return
	}
	_, err = data.Read(id[:])
	chk(err)
	if id.String() != "AIFF" {
		fmt.Println("bad file format")
		return
	}
	var c commonChunk
	var audio io.Reader
	for {
		id, chunk, err := readChunk(data)
		if err == io.EOF {
			break
		}
		chk(err)
		switch id.String() {
		case "COMM":
			chk(binary.Read(chunk, binary.BigEndian, &c))
		case "SSND":
			chunk.Seek(8, 1) //ignore offset and block
			audio = chunk
		default:
			fmt.Printf("ignoring unknown chunk '%s'\n", id)
		}
	}

	//assume 44100 sample rate, mono, 32 bit

	portaudio.Initialize()
	defer portaudio.Terminate()
	out := make([]int32, 8192)
	stream, err := portaudio.OpenDefaultStream(0, 1, 44100, len(out), &out)
	chk(err)
	defer stream.Close()

	chk(stream.Start())
	defer stream.Stop()
	for remaining := int(c.NumSamples); remaining > 0; remaining -= len(out) {
		if len(out) > remaining {
			out = out[:remaining]
		}
		err := binary.Read(audio, binary.BigEndian, out)
		if err == io.EOF {
			break
		}
		chk(err)
		chk(stream.Write())
		select {
		case <-sig:
			return
		default:
		}
	}
}
Example #16
0
func main() {
	if len(os.Args) < 2 {
		fmt.Println("missing required argument:  output file name")
		return
	}
	fmt.Println("Recording.  Press Ctrl-C to stop.")

	sig := make(chan os.Signal, 1)
	signal.Notify(sig, os.Interrupt, os.Kill)

	fileName := os.Args[1]
	if !strings.HasSuffix(fileName, ".aiff") {
		fileName += ".aiff"
	}
	f, err := os.Create(fileName)
	chk(err)

	// form chunk
	_, err = f.WriteString("FORM")
	chk(err)
	chk(binary.Write(f, binary.BigEndian, int32(0))) //total bytes
	_, err = f.WriteString("AIFF")
	chk(err)

	// common chunk
	_, err = f.WriteString("COMM")
	chk(err)
	chk(binary.Write(f, binary.BigEndian, int32(18)))                  //size
	chk(binary.Write(f, binary.BigEndian, int16(1)))                   //channels
	chk(binary.Write(f, binary.BigEndian, int32(0)))                   //number of samples
	chk(binary.Write(f, binary.BigEndian, int16(32)))                  //bits per sample
	_, err = f.Write([]byte{0x40, 0x0e, 0xac, 0x44, 0, 0, 0, 0, 0, 0}) //80-bit sample rate 44100
	chk(err)

	// sound chunk
	_, err = f.WriteString("SSND")
	chk(err)
	chk(binary.Write(f, binary.BigEndian, int32(0))) //size
	chk(binary.Write(f, binary.BigEndian, int32(0))) //offset
	chk(binary.Write(f, binary.BigEndian, int32(0))) //block
	nSamples := 0
	defer func() {
		// fill in missing sizes
		totalBytes := 4 + 8 + 18 + 8 + 8 + 4*nSamples
		_, err = f.Seek(4, 0)
		chk(err)
		chk(binary.Write(f, binary.BigEndian, int32(totalBytes)))
		_, err = f.Seek(22, 0)
		chk(err)
		chk(binary.Write(f, binary.BigEndian, int32(nSamples)))
		_, err = f.Seek(42, 0)
		chk(err)
		chk(binary.Write(f, binary.BigEndian, int32(4*nSamples+8)))
		chk(f.Close())
	}()

	portaudio.Initialize()
	defer portaudio.Terminate()
	in := make([]int32, 64)
	stream, err := portaudio.OpenDefaultStream(1, 0, 44100, len(in), in)
	chk(err)
	defer stream.Close()

	chk(stream.Start())
	for {
		chk(stream.Read())
		chk(binary.Write(f, binary.BigEndian, in))
		nSamples += len(in)
		select {
		case <-sig:
			return
		default:
		}
	}
	chk(stream.Stop())
}