Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 0 additions & 46 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 3 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ description = "Rust bindings for Microsoft Speech SDK."
license = "MIT OR Apache-2.0"
keywords = ["speech", "microsoft", "cognitive", "recognition", "synthesizing"]
categories = ["multimedia", "multimedia::audio", "text-processing"]
exclude = [
"examples/*"
]
exclude = ["examples/*"]
repository = "https://github.com/jabber-tools/cognitive-services-speech-sdk-rs/"
#documentation = "https://jabber-tools.github.io/cognitive_services_speech_sdk_rs/doc/1.0.0/cognitive_services_speech_sdk_rs/index.html"
documentation = "https://docs.rs/cognitive-services-speech-sdk-rs"
Expand All @@ -19,12 +17,11 @@ documentation = "https://docs.rs/cognitive-services-speech-sdk-rs"
[dependencies]
log = "0.4"
env_logger = "0.11.8"
tokio = {version = "1.44.2", features = ["full"]}
tokio = { version = "1.44.2", features = ["full"] }

[build-dependencies]
bindgen = "0.69.4"
zip = "2.6.1"

[dev-dependencies]
rust-embed = "8.4.0"
rodio = "0.20.1"
rodio = "0.20.1"
128 changes: 63 additions & 65 deletions src/audio/pull_audio_input_stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,15 @@ pub trait PullAudioInputStreamCallbacks: Send {
fn get_property(&mut self, id: i32) -> Result<String>;
}

struct CallbackBag {
callbacks: Option<Box<dyn PullAudioInputStreamCallbacks>>,
}

/// PullAudioInputStream represents audio input stream with audio data pulled (read) by Speech Recognizer when needed via *read* method.
/// Passing audio input is controlled by receiver.
pub struct PullAudioInputStream {
pub handle: SmartHandle<SPXAUDIOSTREAMHANDLE>,
callbacks: Option<Box<dyn PullAudioInputStreamCallbacks>>,
callback_bag: Box<CallbackBag>,
}

impl fmt::Debug for PullAudioInputStream {
Expand Down Expand Up @@ -79,7 +83,7 @@ impl PullAudioInputStream {
handle.assume_init(),
audio_stream_release,
),
callbacks: None,
callback_bag: Box::new(CallbackBag { callbacks: None }),
})
}
}
Expand All @@ -97,11 +101,11 @@ impl PullAudioInputStream {
callbacks: Box<dyn PullAudioInputStreamCallbacks>,
register_get_prop_cb: bool,
) -> Result<()> {
self.callbacks = Some(callbacks);
self.callback_bag.callbacks = Some(callbacks);
unsafe {
let mut ret = pull_audio_input_stream_set_callbacks(
self.handle.inner(),
self as *const _ as *mut c_void,
&*self.callback_bag as *const _ as *mut c_void,
Some(Self::cb_read),
Some(Self::cb_close),
);
Expand All @@ -113,7 +117,7 @@ impl PullAudioInputStream {
if register_get_prop_cb {
ret = pull_audio_input_stream_set_getproperty_callback(
self.handle.inner(),
self as *const _ as *mut c_void,
&*self.callback_bag as *const _ as *mut c_void,
Some(Self::cb_get_property),
);
convert_err(
Expand All @@ -129,34 +133,33 @@ impl PullAudioInputStream {
#[allow(non_snake_case)]
#[allow(unused_variables)]
unsafe extern "C" fn cb_read(pvContext: *mut c_void, buffer: *mut u8, size: u32) -> c_int {
let pullstream = &mut *(pvContext as *mut PullAudioInputStream);
let callbacks: &mut Option<Box<(dyn PullAudioInputStreamCallbacks)>> =
&mut pullstream.callbacks;
let callbacks = callbacks.as_mut().unwrap();

let converted_size = usize::try_from(size);
if let Err(conv_err) = converted_size {
error!(
"PullAudioInputStream::cb_read errror when converting size to usize: {}",
conv_err
);
0 // return 0 as we did not read anything
let callback_bag = &mut *(pvContext as *mut CallbackBag);
if let Some(callbacks) = &mut callback_bag.callbacks {
let converted_size = usize::try_from(size);
if let Err(conv_err) = converted_size {
error!(
"PullAudioInputStream::cb_read errror when converting size to usize: {}",
conv_err
);
0 // return 0 as we did not read anything
} else {
let slice_buffer = std::slice::from_raw_parts_mut(buffer, converted_size.unwrap());
let bytes_read = callbacks.read(slice_buffer);
bytes_read as i32
}
} else {
let slice_buffer = std::slice::from_raw_parts_mut(buffer, converted_size.unwrap());
let bytes_read = callbacks.read(slice_buffer);
bytes_read as i32
error!("PullAudioInputStream::cb_read callbacks not defined");
0 // return 0 as we did not read anything
}
}

#[allow(non_snake_case)]
#[allow(unused_variables)]
unsafe extern "C" fn cb_close(pvContext: *mut c_void) {
let pullstream = &mut *(pvContext as *mut PullAudioInputStream);
let callbacks: &mut Option<Box<(dyn PullAudioInputStreamCallbacks)>> =
&mut pullstream.callbacks;
let callbacks = callbacks.as_mut().unwrap();

callbacks.close();
let callback_bag = &mut *(pvContext as *mut CallbackBag);
if let Some(callbacks) = &mut callback_bag.callbacks {
callbacks.close();
}
}

#[allow(non_snake_case)]
Expand All @@ -167,48 +170,43 @@ impl PullAudioInputStream {
value: *mut u8,
size: u32,
) {
let pullstream = &mut *(pvContext as *mut PullAudioInputStream);
let callbacks: &mut Option<Box<(dyn PullAudioInputStreamCallbacks)>> =
&mut pullstream.callbacks;
let callbacks = callbacks.as_mut().unwrap();

let converted_size = usize::try_from(size);
if let Err(conv_err) = converted_size {
error!(
"PullAudioInputStream::cb_get_property errror when converting size to usize: {}",
conv_err
);
return;
}
let converted_size = converted_size.unwrap();

match callbacks.get_property(id) {
Ok(prop_value) => match CString::new(prop_value) {
Ok(c_prop_value) => {
let c_prop_value_bytes_count = c_prop_value.as_bytes().len();
let bytes_count_to_copy = if c_prop_value_bytes_count < converted_size {
c_prop_value_bytes_count
} else {
converted_size
};
std::ptr::copy_nonoverlapping(
c_prop_value.as_ptr(),
value as *mut c_char,
bytes_count_to_copy,
);
}
Err(cstr_err) => {
let callback_bag = &mut *(pvContext as *mut CallbackBag);
if let Some(callbacks) = &mut callback_bag.callbacks {
let converted_size = usize::try_from(size);
if let Err(conv_err) = converted_size {
error!("PullAudioInputStream::cb_get_property errror when converting size to usize: {}", conv_err);
return;
}
let converted_size = converted_size.unwrap();

match callbacks.get_property(id) {
Ok(prop_value) => match CString::new(prop_value) {
Ok(c_prop_value) => {
let c_prop_value_bytes_count = c_prop_value.as_bytes().len();
let bytes_count_to_copy = if c_prop_value_bytes_count < converted_size {
c_prop_value_bytes_count
} else {
converted_size
};
std::ptr::copy_nonoverlapping(
c_prop_value.as_ptr(),
value as *mut c_char,
bytes_count_to_copy,
);
}
Err(cstr_err) => {
error!(
"PullAudioInputStream.cb_get_property error(CString::new): {:?}",
cstr_err
);
}
},
Err(get_prop_err) => {
error!(
"PullAudioInputStream.cb_get_property error(CString::new): {:?}",
cstr_err
"PullAudioInputStream.cb_get_property error(callbacks.get_property): {:?}",
get_prop_err
);
}
},
Err(get_prop_err) => {
error!(
"PullAudioInputStream.cb_get_property error(callbacks.get_property): {:?}",
get_prop_err
);
}
}
}
Expand Down
53 changes: 28 additions & 25 deletions src/audio/push_audio_output_stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,15 @@ pub trait PushAudioOutputStreamCallbacks: Send {
fn close(&mut self);
}

struct CallbackBag {
callbacks: Option<Box<dyn PushAudioOutputStreamCallbacks>>,
}

/// PushAudioOutputStream represents audio output stream with audio data pushed by Speech Synthetizer via *write* method.
/// Speech Synthetizer's caller is passivelly receiving already synthetized audio data via registered *write* callback.
pub struct PushAudioOutputStream {
pub handle: SmartHandle<SPXAUDIOSTREAMHANDLE>,
callbacks: Option<Box<dyn PushAudioOutputStreamCallbacks>>,
callback_bag: Box<CallbackBag>,
}

impl fmt::Debug for PushAudioOutputStream {
Expand All @@ -56,7 +60,7 @@ impl PushAudioOutputStream {
pub unsafe fn from_handle(handle: SPXAUDIOSTREAMHANDLE) -> Result<Self> {
Ok(PushAudioOutputStream {
handle: SmartHandle::create("PushAudioOutputStream", handle, audio_stream_release),
callbacks: None,
callback_bag: Box::new(CallbackBag { callbacks: None }),
})
}

Expand All @@ -74,11 +78,11 @@ impl PushAudioOutputStream {
&mut self,
callbacks: Box<dyn PushAudioOutputStreamCallbacks>,
) -> Result<()> {
self.callbacks = Some(callbacks);
self.callback_bag.callbacks = Some(callbacks);
unsafe {
let ret = push_audio_output_stream_set_callbacks(
self.handle.inner(),
self as *const _ as *mut c_void,
&*self.callback_bag as *const _ as *mut c_void,
Some(Self::cb_write),
Some(Self::cb_close),
);
Expand All @@ -90,33 +94,32 @@ impl PushAudioOutputStream {
#[allow(non_snake_case)]
#[allow(unused_variables)]
unsafe extern "C" fn cb_write(pvContext: *mut c_void, buffer: *mut u8, size: u32) -> c_int {
let pushstream = &mut *(pvContext as *mut PushAudioOutputStream);
let callbacks: &mut Option<Box<(dyn PushAudioOutputStreamCallbacks)>> =
&mut pushstream.callbacks;
let callbacks = callbacks.as_mut().unwrap();

let converted_size = usize::try_from(size);
if let Err(conv_err) = converted_size {
error!(
"PushAudioOutputStream::cb_write errror when converting size to usize: {}",
conv_err
);
0 // return 0 as we did not write anything
let callback_bag = &mut *(pvContext as *mut CallbackBag);
if let Some(callbacks) = &mut callback_bag.callbacks {
let converted_size = usize::try_from(size);
if let Err(conv_err) = converted_size {
error!(
"PushAudioOutputStream::cb_write errror when converting size to usize: {}",
conv_err
);
0 // return 0 as we did not write anything
} else {
let slice_buffer = std::slice::from_raw_parts_mut(buffer, converted_size.unwrap());
let bytes_written = callbacks.write(slice_buffer);
bytes_written as i32
}
} else {
let slice_buffer = std::slice::from_raw_parts_mut(buffer, converted_size.unwrap());
let bytes_written = callbacks.write(slice_buffer);
bytes_written as i32
error!("PushAudioOutputStream::cb_write callbacks not defined");
0 // return 0 as we did not write anything
}
}

#[allow(non_snake_case)]
#[allow(unused_variables)]
unsafe extern "C" fn cb_close(pvContext: *mut c_void) {
let pushstream = &mut *(pvContext as *mut PushAudioOutputStream);
let callbacks: &mut Option<Box<(dyn PushAudioOutputStreamCallbacks)>> =
&mut pushstream.callbacks;
let callbacks = callbacks.as_mut().unwrap();

callbacks.close();
let callback_bag = &mut *(pvContext as *mut CallbackBag);
if let Some(callbacks) = &mut callback_bag.callbacks {
callbacks.close();
}
}
}
Loading
Loading