/
audio_data_stream.go
159 lines (141 loc) · 5.54 KB
/
audio_data_stream.go
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.md file in the project root for full license information.
package speech
import (
"io"
"unsafe"
"github.com/Microsoft/cognitive-services-speech-sdk-go/common"
)
// #include <stdlib.h>
// #include <stdint.h>
// #include <string.h>
// #include <speechapi_c_common.h>
// #include <speechapi_c_audio_stream.h>
//
import "C"
// AudioDataStream represents audio data stream used for operating audio data as a stream.
// Added in version 1.17.0
type AudioDataStream struct {
handle C.SPXHANDLE
// Properties represents the collection of additional properties.
Properties *common.PropertyCollection
}
// Close disposes the associated resources.
func (stream AudioDataStream) Close() {
stream.Properties.Close()
C.audio_stream_release(stream.handle)
}
// NewAudioDataStreamFromHandle creates a new AudioDataStream from a handle (for internal use)
func NewAudioDataStreamFromHandle(handle common.SPXHandle) (*AudioDataStream, error) {
stream := new(AudioDataStream)
stream.handle = uintptr2handle(handle)
/* Properties */
var propBagHandle C.SPXHANDLE
ret := uintptr(C.audio_data_stream_get_property_bag(uintptr2handle(handle), &propBagHandle))
if ret != C.SPX_NOERROR {
return nil, common.NewCarbonError(ret)
}
stream.Properties = common.NewPropertyCollectionFromHandle(handle2uintptr(propBagHandle))
return stream, nil
}
// NewAudioDataStreamFromWavFileInput creates a memory backed AudioDataStream for the specified audio input file.
func NewAudioDataStreamFromWavFileInput(filename string) (*AudioDataStream, error) {
var handle C.SPXHANDLE
fn := C.CString(filename)
defer C.free(unsafe.Pointer(fn))
ret := uintptr(C.audio_data_stream_create_from_file(&handle, fn))
if ret != C.SPX_NOERROR {
return nil, common.NewCarbonError(ret)
}
return NewAudioDataStreamFromHandle(handle2uintptr(handle))
}
// NewAudioDataStreamFromSpeechSynthesisResult creates a memory backed AudioDataStream from given speech synthesis result.
func NewAudioDataStreamFromSpeechSynthesisResult(result *SpeechSynthesisResult) (*AudioDataStream, error) {
var handle C.SPXHANDLE
ret := uintptr(C.audio_data_stream_create_from_result(&handle, result.handle))
if ret != C.SPX_NOERROR {
return nil, common.NewCarbonError(ret)
}
return NewAudioDataStreamFromHandle(handle2uintptr(handle))
}
// GetStatus gets the current status of the audio data stream.
func (stream AudioDataStream) GetStatus() (common.StreamStatus, error) {
var cStatus C.Stream_Status
ret := uintptr(C.audio_data_stream_get_status(stream.handle, &cStatus))
if ret != C.SPX_NOERROR {
return common.StreamStatusUnknown, common.NewCarbonError(ret)
}
return (common.StreamStatus)(cStatus), nil
}
// CanReadData checks whether the stream has enough data to be read.
func (stream AudioDataStream) CanReadData(bytesRequested uint) bool {
return (bool)(C.audio_data_stream_can_read_data(stream.handle, (C.uint32_t)(bytesRequested)))
}
// CanReadDataAt checks whether the stream has enough data to be read, at the specified offset.
func (stream AudioDataStream) CanReadDataAt(bytesRequested uint, off int64) bool {
return (bool)(C.audio_data_stream_can_read_data_from_position(stream.handle, (C.uint32_t)(bytesRequested), (C.uint32_t)(off)))
}
// Read reads a chunk of the audio data stream and fill it to given buffer.
// It returns size of data filled to the buffer and any write error encountered.
func (stream AudioDataStream) Read(buffer []byte) (int, error) {
if len(buffer) == 0 {
return 0, common.NewCarbonError(0x005) // SPXERR_INVALID_ARG
}
var outSize C.uint32_t
ret := uintptr(C.audio_data_stream_read(stream.handle, (*C.uint8_t)(unsafe.Pointer(&buffer[0])), (C.uint32_t)(len(buffer)), &outSize))
if ret != C.SPX_NOERROR {
return 0, common.NewCarbonError(ret)
}
if outSize == 0 {
return 0, io.EOF
}
return (int)(outSize), nil
}
// ReadAt reads a chunk of the audio data stream and fill it to given buffer, at specified offset.
// It returns size of data filled to the buffer and any write error encountered.
func (stream AudioDataStream) ReadAt(buffer []byte, off int64) (int, error) {
if len(buffer) == 0 {
return 0, common.NewCarbonError(0x005) // SPXERR_INVALID_ARG
}
var outSize C.uint32_t
ret := uintptr(C.audio_data_stream_read_from_position(stream.handle, (*C.uint8_t)(unsafe.Pointer(&buffer[0])), (C.uint32_t)(len(buffer)), (C.uint32_t)(off), &outSize))
if ret != C.SPX_NOERROR {
return 0, common.NewCarbonError(ret)
}
if outSize == 0 {
return 0, io.EOF
}
return (int)(outSize), nil
}
// SaveToWavFileAsync saves the audio data to a file, asynchronously.
func (stream AudioDataStream) SaveToWavFileAsync(filename string) chan error {
outcome := make(chan error)
go func() {
fn := C.CString(filename)
defer C.free(unsafe.Pointer(fn))
ret := uintptr(C.audio_data_stream_save_to_wave_file(stream.handle, fn))
if ret != C.SPX_NOERROR {
outcome <- common.NewCarbonError(ret)
} else {
outcome <- nil
}
}()
return outcome
}
// GetOffset gets current offset of the audio data stream.
func (stream AudioDataStream) GetOffset() (int, error) {
var position C.uint32_t
ret := uintptr(C.audio_data_stream_get_position(stream.handle, &position))
if ret != C.SPX_NOERROR {
return 0, common.NewCarbonError(ret)
}
return (int)(position), nil
}
// SetOffset sets current offset of the audio data stream.
func (stream AudioDataStream) SetOffset(offset int) error {
ret := uintptr(C.audio_data_stream_set_position(stream.handle, (C.uint32_t)(offset)))
if ret != C.SPX_NOERROR {
return common.NewCarbonError(ret)
}
return nil
}