File size: 2,250 Bytes
87337b1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/**
 *
 * Agora Real Time Engagement
 * Created by Hai Guo in 2024-08.
 * Copyright (c) 2024 Agora IO. All rights reserved.
 *
 */
// An extension written by Go for TTS
package extension

import (
	"fmt"

	"ten_framework/ten"
)

type pcm struct {
	config *pcmConfig
}

type pcmConfig struct {
	BytesPerSample    int32
	Channel           int32
	ChannelLayout     uint64
	Name              string
	SampleRate        int32
	SamplesPerChannel int32
	Timestamp         int64
}

func defaultPcmConfig() *pcmConfig {
	return &pcmConfig{
		BytesPerSample:    2,
		Channel:           1,
		ChannelLayout:     1,
		Name:              "pcm_frame",
		SampleRate:        44100,
		SamplesPerChannel: 44100 / 100,
		Timestamp:         0,
	}
}

func newPcm(config *pcmConfig) *pcm {
	return &pcm{
		config: config,
	}
}

func (p *pcm) getPcmFrame(tenEnv ten.TenEnv, buf []byte) (pcmFrame ten.AudioFrame, err error) {
	pcmFrame, err = ten.NewAudioFrame(p.config.Name)
	if err != nil {
		tenEnv.LogError(fmt.Sprintf("NewPcmFrame failed, err: %v", err))
		return
	}

	// set pcm frame
	pcmFrame.SetBytesPerSample(p.config.BytesPerSample)
	pcmFrame.SetSampleRate(p.config.SampleRate)
	pcmFrame.SetChannelLayout(p.config.ChannelLayout)
	pcmFrame.SetNumberOfChannels(p.config.Channel)
	pcmFrame.SetTimestamp(p.config.Timestamp)
	pcmFrame.SetDataFmt(ten.AudioFrameDataFmtInterleave)
	pcmFrame.SetSamplesPerChannel(p.config.SamplesPerChannel)
	pcmFrame.AllocBuf(p.getPcmFrameSize())

	borrowedBuf, err := pcmFrame.LockBuf()
	if err != nil {
		tenEnv.LogError(fmt.Sprintf("LockBuf failed, err: %v", err))
		return
	}

	// copy data
	copy(borrowedBuf, buf)

	pcmFrame.UnlockBuf(&borrowedBuf)
	return
}

func (p *pcm) getPcmFrameSize() int {
	return int(p.config.SamplesPerChannel * p.config.Channel * p.config.BytesPerSample)
}

func (p *pcm) newBuf() []byte {
	return make([]byte, p.getPcmFrameSize())
}

func (p *pcm) send(tenEnv ten.TenEnv, buf []byte) (err error) {
	pcmFrame, err := p.getPcmFrame(tenEnv, buf)
	if err != nil {
		tenEnv.LogError(fmt.Sprintf("getPcmFrame failed, err: %v", err))
		return
	}

	// send pcm
	if err = tenEnv.SendAudioFrame(pcmFrame, nil); err != nil {
		tenEnv.LogError(fmt.Sprintf("SendPcmFrame failed, err: %v", err))
		return
	}

	return
}