(req *pb.AudioDecodeRequest)
| 124 | } |
| 125 | |
| 126 | func (o *Opus) AudioDecode(req *pb.AudioDecodeRequest) (*pb.AudioDecodeResult, error) { |
| 127 | if len(req.Frames) == 0 { |
| 128 | return &pb.AudioDecodeResult{ |
| 129 | SampleRate: opusSampleRate, |
| 130 | SamplesPerFrame: opusFrameSize, |
| 131 | }, nil |
| 132 | } |
| 133 | |
| 134 | // Use a persistent decoder when a session ID is provided so that Opus |
| 135 | // prediction state carries across batches. Fall back to a fresh decoder |
| 136 | // for backward compatibility. |
| 137 | sessionID := req.Options["session_id"] |
| 138 | |
| 139 | var cd *cachedDecoder |
| 140 | var ownedDec *Decoder |
| 141 | |
| 142 | if sessionID != "" && o.decoders != nil { |
| 143 | var err error |
| 144 | cd, err = o.getOrCreateDecoder(sessionID) |
| 145 | if err != nil { |
| 146 | return nil, fmt.Errorf("opus decoder create: %w", err) |
| 147 | } |
| 148 | cd.mu.Lock() |
| 149 | defer cd.mu.Unlock() |
| 150 | } else { |
| 151 | dec, err := NewDecoder(opusSampleRate, opusChannels) |
| 152 | if err != nil { |
| 153 | return nil, fmt.Errorf("opus decoder create: %w", err) |
| 154 | } |
| 155 | ownedDec = dec |
| 156 | defer ownedDec.Close() |
| 157 | } |
| 158 | |
| 159 | dec := ownedDec |
| 160 | if cd != nil { |
| 161 | dec = cd.dec |
| 162 | } |
| 163 | |
| 164 | var allSamples []int16 |
| 165 | var samplesPerFrame int32 |
| 166 | |
| 167 | pcm := make([]int16, opusMaxFrameSize) |
| 168 | for _, frame := range req.Frames { |
| 169 | n, err := dec.Decode(frame, pcm, opusMaxFrameSize, false) |
| 170 | if err != nil { |
| 171 | return nil, fmt.Errorf("opus decode: %w", err) |
| 172 | } |
| 173 | if samplesPerFrame == 0 { |
| 174 | samplesPerFrame = int32(n) |
| 175 | } |
| 176 | allSamples = append(allSamples, pcm[:n]...) |
| 177 | } |
| 178 | |
| 179 | return &pb.AudioDecodeResult{ |
| 180 | PcmData: sound.Int16toBytesLE(allSamples), |
| 181 | SampleRate: opusSampleRate, |
| 182 | SamplesPerFrame: samplesPerFrame, |
| 183 | }, nil |
nothing calls this directly
no test coverage detected