func fadeout(s []audio.Sample, samples int) { for i := range s { if r := len(s) - i; r < samples { s[i] *= audio.Sample(r) / audio.Sample(samples) } } }
// readWav reads the wav file at the given path and returns it as a set // of audio samples. // TODO be much less picky about what kinds // of file we accept. func readWav(path string) ([]audio.Sample, error) { f, err := os.Open(path) if err != nil { return nil, fmt.Errorf("cannot open file: %v", err) } defer f.Close() r, err := wav.NewReader(f) if err != nil { return nil, fmt.Errorf("cannot make reader: %v", err) } h := r.Header().Format if h.NumChannels != 1 { return nil, fmt.Errorf("want 1 channel, got %d", h.NumChannels) } if h.SampleRate != drummachine.SampleRate { return nil, fmt.Errorf("want sample rate %d, got %d", drummachine.SampleRate, h.SampleRate) } samples := make([]wav.Sample, r.Remaining()) n, err := r.Read(samples) if n != len(samples) && err != nil { return nil, fmt.Errorf("cannot read samples (%d): %v", n, err) } if n != len(samples) { return nil, fmt.Errorf("only read %d/%d samples", n, len(samples)) } auSamples := make([]audio.Sample, len(samples)) for i, s := range samples { auSamples[i] = audio.Sample(s) } return auSamples, nil }
func normalize(s []audio.Sample) { max := audio.Sample(0) for _, v := range s { if v < 0 { v *= -1 } if v > max { max = v } } if max > 0 { fac := 0.99 / max for i := range s { s[i] *= fac } } }
func (m *Gate) Process(s []audio.Sample) { p := audio.Sample(atomic.LoadInt64(&midiGate)) for i := range s { s[i] = p } }
func (m *Note) Process(s []audio.Sample) { p := (audio.Sample(atomic.LoadInt64(&midiNote)) - 69) / 120 for i := range s { s[i] = p } }