<commit_before>//go:build linux
// +build linux

package output

import (
	"fmt"
	"log"
	"time"

	"github.com/jfreymuth/pulse"
)

type output struct {
	client      *pulse.Client
	stream      *pulse.PlaybackStream
	samplesChan chan []float32
	samplesBuf  []float32
	sampleRate  uint32
	channels    uint8
}

func (o *output) init() {
	if o.client != nil {
		o.stream.Drain()
		o.stream.Close()
		o.stream = nil
	}
	var err error
	o.client, err = pulse.NewClient(pulse.ClientApplicationName("moggio"))
	if err != nil {
		log.Println(err)
		return
	}
	var channels pulse.PlaybackOption
	switch o.channels {
	case 1:
		channels = pulse.PlaybackMono
	case 2:
		channels = pulse.PlaybackStereo
	default:
		log.Println("unsupported channels")
		return
	}
	o.stream, err = o.client.NewPlayback(
		pulse.Float32Reader(o.reader),
		channels,
		pulse.PlaybackSampleRate(int(o.sampleRate)),
		pulse.PlaybackLatency(.1),
	)
	if err != nil {
		log.Println(err)
		return
	}
	o.samplesChan = make(chan []float32)
}

func (o *output) reader(out []float32) (int, error) {
	if len(o.samplesBuf) > 0 {
		n := copy(out, o.samplesBuf)
		o.samplesBuf = o.samplesBuf[n:]
		return n, nil
	}
	select {
	case samples := <-o.samplesChan:
		n := copy(out, samples)
		o.samplesBuf = samples[n:]
		return n, nil
	case <-time.After(100 * time.Millisecond):
		return 0, nil
	}
}

func get(sampleRate, channels int) (Output, error) {
	o := new(output)
	o.sampleRate = uint32(sampleRate)
	o.channels = uint8(channels)
	o.init()
	return o, nil
}

func (o *output) Push(samples []float32) {
	o.samplesChan <- samples
}

func (o *output) Start() {
	// This waits until the buffer is full, so fill it in the background.
	samples := make([]float32, o.stream.BufferSize())
	fmt.Println("dummy", len(samples))
	go o.Push(samples)
	o.stream.Start()
}

func (o *output) Stop() {
	o.stream.Stop()
}<commit_msg>remove debug<commit_after>//go:build linux
// +build linux

package output

import (
	"fmt"
	"log"
	"time"

	"github.com/jfreymuth/pulse"
)

type output struct {
	client      *pulse.Client
	stream      *pulse.PlaybackStream
	samplesChan chan []float32
	samplesBuf  []float32
	sampleRate  uint32
	channels    uint8
}

func (o *output) init() {
	if o.client != nil {
		o.stream.Drain()
		o.stream.Close()
		o.stream = nil
	}
	var err error
	o.client, err = pulse.NewClient(pulse.ClientApplicationName("moggio"))
	if err != nil {
		log.Println(err)
		return
	}
	var channels pulse.PlaybackOption
	switch o.channels {
	case 1:
		channels = pulse.PlaybackMono
	case 2:
		channels = pulse.PlaybackStereo
	default:
		log.Println("unsupported channels")
		return
	}
	o.stream, err = o.client.NewPlayback(
		pulse.Float32Reader(o.reader),
		channels,
		pulse.PlaybackSampleRate(int(o.sampleRate)),
		pulse.PlaybackLatency(.1),
	)
	if err != nil {
		log.Println(err)
		return
	}
	o.samplesChan = make(chan []float32)
}

func (o *output) reader(out []float32) (int, error) {
	if len(o.samplesBuf) > 0 {
		n := copy(out, o.samplesBuf)
		o.samplesBuf = o.samplesBuf[n:]
		return n, nil
	}
	select {
	case samples := <-o.samplesChan:
		n := copy(out, samples)
		o.samplesBuf = samples[n:]
		return n, nil
	case <-time.After(100 * time.Millisecond):
		return 0, nil
	}
}

func get(sampleRate, channels int) (Output, error) {
	o := new(output)
	o.sampleRate = uint32(sampleRate)
	o.channels = uint8(channels)
	o.init()
	return o, nil
}

func (o *output) Push(samples []float32) {
	o.samplesChan <- samples
}

func (o *output) Start() {
	// This waits until the buffer is full, so fill it in the background.
	samples := make([]float32, o.stream.BufferSize())
	go o.Push(samples)
	o.stream.Start()
}

func (o *output) Stop() {
	o.stream.Stop()
}
{'fraction_non_alphanumeric': 0.14359252235166622, 'fraction_numerical': 0.015172040097534544, 'mean_word_length': 3.6734177215189874, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5346821', 'n_tokens_mistral': 1513, 'n_tokens_neox': 1389, 'n_words': 339}