Exemple #1
0
func (c *Context) Play() {
	c.Lock()
	defer c.Unlock()
	n := c.source.BuffersProcessed()
	if n > 0 {
		rm, split := c.queue[:n], c.queue[n:]
		c.queue = split
		c.source.UnqueueBuffers(rm...)
		al.DeleteBuffers(rm...)
	}
	for len(c.queue) < QUEUE {
		b := al.GenBuffers(1)
		buf := make([]byte, NS*CZ)
		for n := 0; n < NS*CZ; n += CZ {
			v := int16(float32(32767) * c.oscilator())
			binary.LittleEndian.PutUint16(buf[n:n+2], uint16(v))
		}
		b[0].BufferData(Fmt, buf, SampleRate)
		c.source.QueueBuffers(b...)
		c.queue = append(c.queue, b...)
	}
	if c.source.State() != al.Playing {
		al.PlaySources(c.source)
	}
}
Exemple #2
0
func NewPlayer(sampleRate, channelNum, bytesPerSample int) (*Player, error) {
	var p *Player
	if err := al.OpenDevice(); err != nil {
		return nil, fmt.Errorf("driver: OpenAL initialization failed: %v", err)
	}
	s := al.GenSources(1)
	if e := al.Error(); e != 0 {
		return nil, fmt.Errorf("driver: al.GenSources error: %d", e)
	}
	p = &Player{
		alSource:   s[0],
		alBuffers:  []al.Buffer{},
		sampleRate: sampleRate,
		alFormat:   alFormat(channelNum, bytesPerSample),
	}
	runtime.SetFinalizer(p, (*Player).Close)

	bs := al.GenBuffers(maxBufferNum)
	const bufferSize = 1024
	emptyBytes := make([]byte, bufferSize)
	for _, b := range bs {
		// Note that the third argument of only the first buffer is used.
		b.BufferData(p.alFormat, emptyBytes, int32(p.sampleRate))
		p.alSource.QueueBuffers(b)
	}
	al.PlaySources(p.alSource)
	return p, nil
}
Exemple #3
0
// PlaySound will play the key's sound if the coordinates lay within the key itself.
func (k *PianoKey) PlaySound(x float32, y float32, frameData util.FrameData) bool {
	if !k.pressed && k.DoesCoordsOverlapKey(x, y, frameData) {
		k.pressed = true
		al.PlaySources(k.soundSources...)
		return true
	}
	return false
}
Exemple #4
0
// Play buffers the source audio to the audio device and starts
// to play the source.
// If the player paused or stopped, it reuses the previously buffered
// resources to keep playing from the time it has paused or stopped.
func (p *Player) Play() error {
	if p == nil {
		return nil
	}
	// Prepares if the track hasn't been buffered before.
	if err := p.prepare(0, false); err != nil {
		return err
	}
	al.PlaySources(p.source)
	return lastErr()
}
Exemple #5
0
func (as *AudioSystem) Update(entity *ecs.Entity, dt float32) {
	var ac *AudioComponent
	var ok bool
	if ac, ok = entity.ComponentFast(ac).(*AudioComponent); !ok {
		return
	}

	if ac.player == nil {
		f := Files.Sound(ac.File)
		if f == nil {
			return
		}

		var err error
		ac.player, err = NewPlayer(f, 0, 0)
		if err != nil {
			log.Println("Error initializing AudioSystem:", err)
			return
		}
	}

	if ac.player.State() != Playing {
		if ac.player.State() == Stopped {
			if !ac.Repeat {
				al.RewindSources(ac.player.source)
				al.StopSources(ac.player.source)
				entity.RemoveComponent(ac)
				return
			}
		}

		// Prepares if the track hasn't been buffered before.
		if err := ac.player.prepare(ac.Background, 0, false); err != nil {
			log.Println("Error initializing AudioSystem:", err)
			return
		}

		al.PlaySources(ac.player.source)

		if !ac.Background {
			var space *SpaceComponent
			var ok bool
			if space, ok = entity.ComponentFast(space).(*SpaceComponent); !ok {
				return
			}

			ac.player.source.SetPosition(al.Vector{
				(space.Position.X + space.Width/2) / Width(),
				(space.Position.Y + space.Height/2) / Height(),
				0})
		}
	}
}
Exemple #6
0
func (a *AudioSystem) Update(dt float32) {
	for _, e := range a.entities {
		if e.AudioComponent.player == nil {
			f := Files.Sound(e.AudioComponent.File)
			if f == nil {
				log.Println("Audio file not loaded:", e.AudioComponent.File)
				continue
			}

			var err error
			e.AudioComponent.player, err = NewPlayer(f, 0, 0)
			if err != nil {
				log.Println("Error initializing AudioComponent:", err)
				continue
			}
		}

		if MasterVolume != a.cachedVolume {
			e.AudioComponent.SetVolume(e.AudioComponent.RawVolume)
		}

		if e.AudioComponent.player.State() != Playing {
			if e.AudioComponent.player.State() == Stopped {
				if !e.AudioComponent.Repeat {
					al.RewindSources(e.AudioComponent.player.source)
					al.StopSources(e.AudioComponent.player.source)
					// Remove it from this system, defer because we want to be sure it doesn't interfere with
					// looping over a.entities
					defer a.Remove(*e.BasicEntity)
					continue
				}
			}

			// Prepares if the track hasn't been buffered before.
			if err := e.AudioComponent.player.prepare(e.AudioComponent.Background, 0, false); err != nil {
				log.Println("Error initializing AudioComponent:", err)
				continue
			}

			al.PlaySources(e.AudioComponent.player.source)

			if !e.AudioComponent.Background {
				e.AudioComponent.player.source.SetPosition(al.Vector{
					(e.SpaceComponent.Position.X + e.SpaceComponent.Width/2) / GameWidth(), // TODO: ensure we're using correct Width/Height()
					(e.SpaceComponent.Position.Y + e.SpaceComponent.Height/2) / GameHeight(),
					0,
				})
			}
		}
	}
}
Exemple #7
0
func (k *PianoKey) Press(f int) {
	k.Angle = 3.14 / 16
	k.Finger = f
	light.Intensities = k.LightColor
	bp := k.source.BuffersProcessed()
	if bp > 0 {
		b := make([]al.Buffer, bp)
		k.source.UnqueueBuffers(b...)
	}
	if k.source.BuffersQueued() == 0 {
		k.source.QueueBuffers(k.buffers[0])
		al.PlaySources(k.source)
	}
}
Exemple #8
0
// Seek moves the play head to the given offset relative to the start of the source.
func (p *Player) Seek(offset time.Duration) error {
	if p == nil {
		return nil
	}
	if err := p.Stop(); err != nil {
		return err
	}
	size := durToByteOffset(p.t, offset)
	if err := p.prepare(size, true); err != nil {
		return err
	}
	al.PlaySources(p.source)
	return lastErr()
}
Exemple #9
0
func (p *Player) Proceed(data []byte) error {
	if err := al.Error(); err != 0 {
		return fmt.Errorf("driver: before proceed: %d", err)
	}
	processedNum := p.alSource.BuffersProcessed()
	if 0 < processedNum {
		bufs := make([]al.Buffer, processedNum)
		p.alSource.UnqueueBuffers(bufs...)
		if err := al.Error(); err != 0 {
			return fmt.Errorf("driver: Unqueue in process: %d", err)
		}
		p.alBuffers = append(p.alBuffers, bufs...)
	}

	if len(p.alBuffers) == 0 {
		// This can happen (#207)
		return nil
	}
	buf := p.alBuffers[0]
	p.alBuffers = p.alBuffers[1:]
	buf.BufferData(p.alFormat, data, int32(p.sampleRate))
	p.alSource.QueueBuffers(buf)
	if err := al.Error(); err != 0 {
		return fmt.Errorf("driver: Queue in process: %d", err)
	}

	if p.alSource.State() == al.Stopped || p.alSource.State() == al.Initial {
		al.RewindSources(p.alSource)
		al.PlaySources(p.alSource)
		if err := al.Error(); err != 0 {
			return fmt.Errorf("driver: PlaySource in process: %d", err)
		}
	}

	return nil
}
Exemple #10
0
func Tick() {
	start := time.Now()

	if code := al.DeviceError(); code != 0 {
		log.Printf("snd/al: unknown device error [err=%v]\n", code)
	}
	if code := al.Error(); code != 0 {
		log.Printf("snd/al: unknown error [err=%v]\n", code)
	}

	bufs := hwa.buf.Get()

	for _, buf := range bufs {
		hwa.tc++

		// TODO the general idea here is that GetInputs is rather cheap to call, even with the
		// current first-draft implementation, so it could only return inputs that are actually
		// turned on. This would introduce software latency determined by snd.DefaultBufferLen
		// as turning an input back on would not get picked up until the next iteration.
		// if !realtime {
		// hwa.inputs = snd.GetInputs(hwa.in)
		// }

		dp.Dispatch(hwa.tc, hwa.inputs...)

		for i, x := range hwa.in.Samples() {
			// clip
			if x > 1 {
				x = 1
			} else if x < -1 {
				x = -1
			}
			n := int16(math.MaxInt16 * x)
			hwa.out[2*i] = byte(n)
			hwa.out[2*i+1] = byte(n >> 8)
		}

		buf.BufferData(hwa.format, hwa.out, int32(hwa.in.SampleRate()))
		if code := al.Error(); code != 0 {
			log.Printf("snd/al: buffer data failed [err=%v]\n", code)
		}
	}

	if len(bufs) != 0 {
		hwa.source.QueueBuffers(bufs)
	}
	if code := al.Error(); code != 0 {
		log.Printf("snd/al: queue buffer failed [err=%v]\n", code)
	}

	switch hwa.source.State() {
	case al.Initial:
		al.PlaySources(hwa.source)
	case al.Playing:
	case al.Paused:
	case al.Stopped:
		hwa.underruns++
		al.PlaySources(hwa.source)
	}

	hwa.tdur += time.Now().Sub(start)
}
Exemple #11
0
// PlaySound plays the sound of the source i
func PlaySound(i int) {
	al.PlaySources(sources[i])
}