// SetFire to represent a single audio source playing at a specific time in the future (in time.Duration from play start), with sustain time.Duration, volume from 0 to 1, and pan from -1 to +1 func SetFire(source string, begin time.Duration, sustain time.Duration, volume float64, pan float64) *fire.Fire { mixPrepareSource(mixSourcePrefix + source) beginTz := spec.Tz(begin.Nanoseconds() / masterTzDur.Nanoseconds()) var endTz spec.Tz if sustain != 0 { endTz = beginTz + spec.Tz(sustain.Nanoseconds()/masterTzDur.Nanoseconds()) } f := fire.New(mixSourcePrefix+source, beginTz, endTz, volume, pan) mixReadyFires = append(mixReadyFires, f) return f }
func TestBase(t *testing.T) { testLengthTz := spec.Tz(100) src := "sound.wav" bgnTz := spec.Tz(5984) endTz := bgnTz + testLengthTz vol := float64(1) pan := float64(0) fire := New(src, bgnTz, endTz, vol, pan) // before start: assert.Equal(t, spec.Tz(0), fire.At(bgnTz-2)) assert.Equal(t, spec.Tz(0), fire.At(bgnTz-1)) assert.Equal(t, fireStateReady, fire.state) assert.Equal(t, true, fire.IsAlive()) // start: assert.Equal(t, spec.Tz(0), fire.At(bgnTz)) assert.Equal(t, fireStatePlay, fire.state) assert.Equal(t, true, fire.IsAlive()) // after start / before end: for n := spec.Tz(1); n < testLengthTz; n++ { assert.Equal(t, spec.Tz(n), fire.At(bgnTz+n)) } // end: assert.Equal(t, testLengthTz, fire.At(endTz)) assert.Equal(t, fireStateDone, fire.state) assert.Equal(t, false, fire.IsAlive()) // after end: assert.Equal(t, spec.Tz(0), fire.At(endTz+1)) }
// Configure the mixer frequency, format, channels & sample rate. func Configure(s spec.AudioSpec) { masterSpec = &s masterFreq = float64(s.Freq) masterTzDur = time.Second / time.Duration(masterFreq) masterCycleDurTz = spec.Tz(masterFreq) source.Configure(s) }
// OutputContinueTo to mix and output as []byte via stdout, up to a specified duration-since-start func OutputContinueTo(t time.Duration) { deltaDur := t - outputToDur deltaTz := spec.Tz(masterFreq * float64((deltaDur)/time.Second)) debug.Printf("mix.OutputContinueTo(%+v) deltaDur:%+v nowTz:%+v deltaTz:%+v begin...", t, deltaDur, nowTz, deltaTz) bind.OutputNext(deltaTz) outputToDur = t debug.Printf("mix.OutputContinueTo(%+v) ...done! nowTz:%+v outputToDur:%+v", t, nowTz, outputToDur) }
func GetLength(src string) spec.Tz { source := Get(src) if source != nil { return source.Length() } else { return spec.Tz(0) } }
func testSourceAssertSound(t *testing.T, source *Source, channels int) (totalSoundMovement sample.Value) { for tz := spec.Tz(0); tz < source.Length(); tz++ { smp := source.SampleAt(tz, 1, 0) assert.Equal(t, channels, len(smp)) for c := 0; c < channels; c++ { totalSoundMovement += smp[c].Abs() } } return }
func (s *Source) load() { s.state = LOADING s.sample, s.audioSpec = bind.LoadWAV(s.URL) if s.audioSpec == nil { // TODO: handle errors loading file debug.Printf("could not load WAV %s\n", s.URL) } s.maxTz = spec.Tz(len(s.sample)) s.state = READY }
// GetCycleDurationTz sets the duration of a mix cycle. func SetCycleDuration(d time.Duration) { if masterFreq == 0 { panic("Must specify mixing frequency before setting cycle duration!") } masterCycleDurTz = spec.Tz((d / time.Second) * time.Duration(masterFreq)) }
func TestSetGetMixCycleDuration(t *testing.T) { testAPISetup() SetMixCycleDuration(2 * time.Second) assert.Equal(t, spec.Tz(88200), mix.GetCycleDurationTz()) }
func OutputNext(numSamples spec.Tz) (err error) { for n := spec.Tz(0); n < numSamples; n++ { writer.Write(sample.OutNextBytes()) } return }