Beispiel #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)
	}
}
Beispiel #2
0
func CloseDevice() error {
	al.DeleteBuffers(hwa.buf.bufs)
	al.DeleteSources(hwa.source)
	al.CloseDevice()
	hwa = nil
	return nil
}
Beispiel #3
0
func (c *Context) Close() {
	c.Lock()
	defer c.Unlock()
	al.StopSources(c.source)
	c.source.UnqueueBuffers(c.queue...)
	al.DeleteBuffers(c.queue...)
	c.queue = nil
	al.DeleteSources(c.source)
}
Beispiel #4
0
func (p *Player) prepare(offset int64, force bool) error {
	p.mu.Lock()
	if !force && p.prep {
		p.mu.Unlock()
		return nil
	}
	p.mu.Unlock()

	if p.t.hasHeader {
		offset += headerSize
	}
	if _, err := p.t.src.Seek(offset, 0); err != nil {
		return err
	}
	var bufs []al.Buffer
	// TODO(jbd): Limit the number of buffers in use, unqueue and reuse
	// the existing buffers as buffers are processed.
	buf := make([]byte, 128*1024)
	size := offset
	for {
		n, err := p.t.src.Read(buf)
		if n > 0 {
			size += int64(n)
			b := al.GenBuffers(1)
			b[0].BufferData(formatCodes[p.t.format], buf[:n], int32(p.t.samplesPerSecond))
			bufs = append(bufs, b[0])
		}
		if err == io.EOF {
			break
		}
		if err != nil {
			return err
		}
	}

	p.mu.Lock()
	if len(p.bufs) > 0 {
		p.source.UnqueueBuffers(p.bufs...)
		al.DeleteBuffers(p.bufs...)
	}
	p.sizeBytes = size
	p.bufs = bufs
	p.prep = true
	if len(bufs) > 0 {
		p.source.QueueBuffers(bufs...)
	}
	p.mu.Unlock()
	return nil
}
Beispiel #5
0
// Close closes the device and frees the underlying resources
// used by the player.
// It should be called as soon as the player is not in-use anymore.
func (p *Player) Close() error {
	if p == nil {
		return nil
	}
	if p.source != 0 {
		al.DeleteSources(p.source)
	}
	p.mu.Lock()
	if len(p.bufs) > 0 {
		al.DeleteBuffers(p.bufs...)
	}
	p.mu.Unlock()
	p.t.src.Close()
	return nil
}
Beispiel #6
0
func (p *Player) prepare(background bool, offset int64, force bool) error {
	p.mu.Lock()
	if !force && p.prep {
		p.mu.Unlock()
		return nil
	}
	p.mu.Unlock()

	if p.t.hasHeader {
		offset += headerSize
	}
	if _, err := p.t.src.Seek(offset, 0); err != nil {
		return err
	}
	var bufs []al.Buffer
	// TODO(jbd): Limit the number of buffers in use, unqueue and reuse
	// the existing buffers as buffers are processed.
	buf := make([]byte, 128*1024)
	size := offset
	for {
		n, err := p.t.src.Read(buf)
		if n > 0 {
			size += int64(n)
			b := al.GenBuffers(1)
			if !background && p.t.format == Stereo16 {
				inputBuffer := bytes.NewBuffer(buf)
				outputBuffer := new(bytes.Buffer)
				var left, right int16

				// TODO: this might not be the best way to convert Stereo16 to Mono16, but it's something
				for converted := 0; converted < n; converted += 4 {
					binary.Read(inputBuffer, binary.LittleEndian, &left)
					binary.Read(inputBuffer, binary.LittleEndian, &right)

					binary.Write(outputBuffer, binary.LittleEndian, int16((int32(left)+int32(right))/2))
				}
				b[0].BufferData(formatCodes[Mono16], outputBuffer.Bytes(), int32(p.t.samplesPerSecond/2))

			} else {
				b[0].BufferData(formatCodes[p.t.format], buf[:n], int32(p.t.samplesPerSecond))
			}
			bufs = append(bufs, b[0])
		}
		if err == io.EOF {
			break
		}
		if err != nil {
			return err
		}
	}

	p.mu.Lock()
	if len(p.bufs) > 0 {
		p.source.UnqueueBuffers(p.bufs...)
		al.DeleteBuffers(p.bufs...)
	}
	p.sizeBytes = size
	p.bufs = bufs
	p.prep = true
	if len(bufs) > 0 {
		p.source.QueueBuffers(bufs...)
	}
	p.mu.Unlock()
	return nil
}
Beispiel #7
0
// DestroyKey cleans up any resources for the key when destorying the key.
func (k *PianoKey) DestroyKey(glctx gl.Context) {
	glctx.DeleteBuffer(k.glBuf)
	al.DeleteSources(k.soundSources...)
	al.DeleteBuffers(k.soundBuffers)
	al.CloseDevice()
}