update v2.x
This commit is contained in:
parent
f60d8c512c
commit
bbb67ae87e
|
@ -44,11 +44,11 @@ static int session_handle_event(const tsip_event_t *sipevent);
|
|||
//# endif
|
||||
#endif
|
||||
|
||||
SipStack::SipStack(SipCallback* callback_, const char* realm_uri, const char* impi_uri, const char* impu_uri)
|
||||
SipStack::SipStack(SipCallback* pCallback, const char* realm_uri, const char* impi_uri, const char* impu_uri)
|
||||
:SafeObject()
|
||||
{
|
||||
this->debugCallback = tsk_null;
|
||||
this->callback = callback_;
|
||||
m_pDebugCallback = tsk_null;
|
||||
m_pCallback = pCallback;
|
||||
|
||||
/* Initialize network layer */
|
||||
if(SipStack::count == 0){
|
||||
|
@ -57,7 +57,7 @@ SipStack::SipStack(SipCallback* callback_, const char* realm_uri, const char* im
|
|||
}
|
||||
|
||||
/* Creates stack handle */
|
||||
this->handle = tsip_stack_create(stack_callback, realm_uri, impi_uri, impu_uri,
|
||||
m_pHandle = tsip_stack_create(stack_callback, realm_uri, impi_uri, impu_uri,
|
||||
TSIP_STACK_SET_LOCAL_IP(DEFAULT_LOCAL_IP),
|
||||
TSIP_STACK_SET_USERDATA(this), /* used as context (useful for server-initiated requests) */
|
||||
TSIP_STACK_SET_NULL());
|
||||
|
@ -70,7 +70,7 @@ SipStack::~SipStack()
|
|||
this->stop();
|
||||
|
||||
/* Destroy stack handle */
|
||||
TSK_OBJECT_SAFE_FREE(this->handle);
|
||||
TSK_OBJECT_SAFE_FREE(m_pHandle);
|
||||
|
||||
/* DeInitialize the network layer (only if last stack) */
|
||||
if(--SipStack::count == 0){
|
||||
|
@ -81,13 +81,13 @@ SipStack::~SipStack()
|
|||
|
||||
bool SipStack::start()
|
||||
{
|
||||
return (tsip_stack_start(this->handle) == 0);
|
||||
return (tsip_stack_start(m_pHandle) == 0);
|
||||
}
|
||||
|
||||
bool SipStack::setDebugCallback(DDebugCallback* callback)
|
||||
bool SipStack::setDebugCallback(DDebugCallback* pCallback)
|
||||
{
|
||||
if(this && callback){
|
||||
this->debugCallback = callback;
|
||||
if(this && pCallback){
|
||||
m_pDebugCallback = pCallback;
|
||||
tsk_debug_set_arg_data(this);
|
||||
tsk_debug_set_info_cb(DDebugCallback::debug_info_cb);
|
||||
tsk_debug_set_warn_cb(DDebugCallback::debug_warn_cb);
|
||||
|
@ -95,7 +95,7 @@ bool SipStack::setDebugCallback(DDebugCallback* callback)
|
|||
tsk_debug_set_fatal_cb(DDebugCallback::debug_fatal_cb);
|
||||
}
|
||||
else if(this){
|
||||
this->debugCallback = tsk_null;
|
||||
m_pDebugCallback = tsk_null;
|
||||
tsk_debug_set_arg_data(tsk_null);
|
||||
tsk_debug_set_info_cb(tsk_null);
|
||||
tsk_debug_set_warn_cb(tsk_null);
|
||||
|
@ -108,7 +108,7 @@ bool SipStack::setDebugCallback(DDebugCallback* callback)
|
|||
|
||||
bool SipStack::setRealm(const char* realm_uri)
|
||||
{
|
||||
int ret = tsip_stack_set(this->handle,
|
||||
int ret = tsip_stack_set(m_pHandle,
|
||||
TSIP_STACK_SET_REALM(realm_uri),
|
||||
TSIP_STACK_SET_NULL());
|
||||
return (ret == 0);
|
||||
|
@ -116,21 +116,21 @@ bool SipStack::setRealm(const char* realm_uri)
|
|||
|
||||
bool SipStack::setIMPI(const char* impi)
|
||||
{
|
||||
return (tsip_stack_set(this->handle,
|
||||
return (tsip_stack_set(m_pHandle,
|
||||
TSIP_STACK_SET_IMPI(impi),
|
||||
TSIP_STACK_SET_NULL()) == 0);
|
||||
}
|
||||
|
||||
bool SipStack::setIMPU(const char* impu_uri)
|
||||
{
|
||||
return (tsip_stack_set(this->handle,
|
||||
return (tsip_stack_set(m_pHandle,
|
||||
TSIP_STACK_SET_IMPU(impu_uri),
|
||||
TSIP_STACK_SET_NULL()) == 0);
|
||||
}
|
||||
|
||||
bool SipStack::setPassword(const char* password)
|
||||
{
|
||||
return (tsip_stack_set(this->handle,
|
||||
return (tsip_stack_set(m_pHandle,
|
||||
TSIP_STACK_SET_PASSWORD(password),
|
||||
TSIP_STACK_SET_NULL()) == 0);
|
||||
}
|
||||
|
@ -138,14 +138,14 @@ bool SipStack::setPassword(const char* password)
|
|||
bool SipStack::setAMF(const char* amf)
|
||||
{
|
||||
uint16_t _amf = (uint16_t)tsk_atox(amf);
|
||||
return (tsip_stack_set(this->handle,
|
||||
return (tsip_stack_set(m_pHandle,
|
||||
TSIP_STACK_SET_IMS_AKA_AMF(_amf),
|
||||
TSIP_STACK_SET_NULL()) == 0);
|
||||
}
|
||||
|
||||
bool SipStack::setOperatorId(const char* opid)
|
||||
{
|
||||
return (tsip_stack_set(this->handle,
|
||||
return (tsip_stack_set(m_pHandle,
|
||||
TSIP_STACK_SET_IMS_AKA_OPERATOR_ID(opid),
|
||||
TSIP_STACK_SET_NULL()) == 0);
|
||||
}
|
||||
|
@ -153,14 +153,14 @@ bool SipStack::setOperatorId(const char* opid)
|
|||
bool SipStack::setProxyCSCF(const char* fqdn, unsigned short port, const char* transport, const char* ipversion)
|
||||
{
|
||||
unsigned _port = port;//promote
|
||||
return (tsip_stack_set(this->handle,
|
||||
return (tsip_stack_set(m_pHandle,
|
||||
TSIP_STACK_SET_PROXY_CSCF(fqdn, _port, transport, ipversion),
|
||||
TSIP_STACK_SET_NULL()) == 0);
|
||||
}
|
||||
|
||||
bool SipStack::setLocalIP(const char* ip)
|
||||
{
|
||||
return (tsip_stack_set(this->handle,
|
||||
return (tsip_stack_set(m_pHandle,
|
||||
TSIP_STACK_SET_LOCAL_IP(ip),
|
||||
TSIP_STACK_SET_NULL()) == 0);
|
||||
}
|
||||
|
@ -168,34 +168,34 @@ bool SipStack::setLocalIP(const char* ip)
|
|||
bool SipStack::setLocalPort(unsigned short port)
|
||||
{
|
||||
unsigned _port = port;//promote
|
||||
return (tsip_stack_set(this->handle,
|
||||
return (tsip_stack_set(m_pHandle,
|
||||
TSIP_STACK_SET_LOCAL_PORT(_port),
|
||||
TSIP_STACK_SET_NULL()) == 0);
|
||||
}
|
||||
|
||||
bool SipStack::setEarlyIMS(bool enabled){
|
||||
return (tsip_stack_set(this->handle,
|
||||
return (tsip_stack_set(m_pHandle,
|
||||
TSIP_STACK_SET_EARLY_IMS(enabled? tsk_true : tsk_false),
|
||||
TSIP_STACK_SET_NULL()) == 0);
|
||||
}
|
||||
|
||||
bool SipStack::addHeader(const char* name, const char* value)
|
||||
{
|
||||
return (tsip_stack_set(this->handle,
|
||||
return (tsip_stack_set(m_pHandle,
|
||||
TSIP_STACK_SET_HEADER(name, value),
|
||||
TSIP_STACK_SET_NULL()) == 0);
|
||||
}
|
||||
|
||||
bool SipStack::removeHeader(const char* name)
|
||||
{
|
||||
return (tsip_stack_set(this->handle,
|
||||
return (tsip_stack_set(m_pHandle,
|
||||
TSIP_STACK_UNSET_HEADER(name),
|
||||
TSIP_STACK_SET_NULL()) == 0);
|
||||
}
|
||||
|
||||
bool SipStack::addDnsServer(const char* ip)
|
||||
{
|
||||
return (tsip_stack_set(this->handle,
|
||||
return (tsip_stack_set(m_pHandle,
|
||||
TSIP_STACK_SET_DNS_SERVER(ip),
|
||||
TSIP_STACK_SET_NULL()) == 0);
|
||||
}
|
||||
|
@ -203,21 +203,21 @@ bool SipStack::addDnsServer(const char* ip)
|
|||
bool SipStack::setDnsDiscovery(bool enabled)
|
||||
{
|
||||
tsk_bool_t _enabled = enabled;// 32bit/64bit workaround
|
||||
return (tsip_stack_set(this->handle,
|
||||
return (tsip_stack_set(m_pHandle,
|
||||
TSIP_STACK_SET_DISCOVERY_NAPTR(_enabled),
|
||||
TSIP_STACK_SET_NULL()) == 0);
|
||||
}
|
||||
|
||||
bool SipStack::setAoR(const char* ip, int port)
|
||||
{
|
||||
return (tsip_stack_set(this->handle,
|
||||
return (tsip_stack_set(m_pHandle,
|
||||
TSIP_STACK_SET_AOR(ip, port),
|
||||
TSIP_STACK_SET_NULL()) == 0);
|
||||
}
|
||||
|
||||
bool SipStack::setModeServer()
|
||||
{
|
||||
return (tsip_stack_set(this->handle,
|
||||
return (tsip_stack_set(m_pHandle,
|
||||
TSIP_STACK_SET_MODE_SERVER(),
|
||||
TSIP_STACK_SET_NULL()) == 0);
|
||||
}
|
||||
|
@ -225,21 +225,21 @@ bool SipStack::setModeServer()
|
|||
bool SipStack::setSigCompParams(unsigned dms, unsigned sms, unsigned cpb, bool enablePresDict)
|
||||
{
|
||||
tsk_bool_t _enablePresDict= enablePresDict;// 32bit/64bit workaround
|
||||
return (tsip_stack_set(this->handle,
|
||||
return (tsip_stack_set(m_pHandle,
|
||||
TSIP_STACK_SET_SIGCOMP(dms, sms, cpb, _enablePresDict),
|
||||
TSIP_STACK_SET_NULL()) == 0);
|
||||
}
|
||||
|
||||
bool SipStack::addSigCompCompartment(const char* compId)
|
||||
{
|
||||
return (tsip_stack_set(this->handle,
|
||||
return (tsip_stack_set(m_pHandle,
|
||||
TSIP_STACK_SET_SIGCOMP_NEW_COMPARTMENT(compId),
|
||||
TSIP_STACK_SET_NULL()) == 0);
|
||||
}
|
||||
|
||||
bool SipStack::removeSigCompCompartment(const char* compId)
|
||||
{
|
||||
return (tsip_stack_set(this->handle,
|
||||
return (tsip_stack_set(m_pHandle,
|
||||
TSIP_STACK_UNSET_SIGCOMP_COMPARTMENT(compId),
|
||||
TSIP_STACK_SET_NULL()) == 0);
|
||||
}
|
||||
|
@ -247,14 +247,14 @@ bool SipStack::removeSigCompCompartment(const char* compId)
|
|||
bool SipStack::setSTUNServer(const char* ip, unsigned short port)
|
||||
{
|
||||
unsigned _port = port;//promote
|
||||
return (tsip_stack_set(this->handle,
|
||||
return (tsip_stack_set(m_pHandle,
|
||||
TSIP_STACK_SET_STUN_SERVER(ip, _port),
|
||||
TSIP_STACK_SET_NULL()) == 0);
|
||||
}
|
||||
|
||||
bool SipStack::setSTUNCred(const char* login, const char* password)
|
||||
{
|
||||
return (tsip_stack_set(this->handle,
|
||||
return (tsip_stack_set(m_pHandle,
|
||||
TSIP_STACK_SET_STUN_CRED(login, password),
|
||||
TSIP_STACK_SET_NULL()) == 0);
|
||||
}
|
||||
|
@ -262,14 +262,14 @@ bool SipStack::setSTUNCred(const char* login, const char* password)
|
|||
bool SipStack::setTLSSecAgree(bool enabled)
|
||||
{
|
||||
tsk_bool_t _enable = enabled;
|
||||
return (tsip_stack_set(this->handle,
|
||||
return (tsip_stack_set(m_pHandle,
|
||||
TSIP_STACK_SET_SECAGREE_TLS(_enable),
|
||||
TSIP_STACK_SET_NULL()) == 0);
|
||||
}
|
||||
|
||||
bool SipStack::setSSLCretificates(const char* privKey, const char* pubKey, const char* caKey)
|
||||
{
|
||||
return (tsip_stack_set(this->handle,
|
||||
return (tsip_stack_set(m_pHandle,
|
||||
TSIP_STACK_SET_TLS_CERTS(caKey, pubKey, privKey),
|
||||
TSIP_STACK_SET_NULL()) == 0);
|
||||
}
|
||||
|
@ -277,21 +277,21 @@ bool SipStack::setSSLCretificates(const char* privKey, const char* pubKey, const
|
|||
bool SipStack::setIPSecSecAgree(bool enabled)
|
||||
{
|
||||
tsk_bool_t _enable = enabled;
|
||||
return (tsip_stack_set(this->handle,
|
||||
return (tsip_stack_set(m_pHandle,
|
||||
TSIP_STACK_SET_SECAGREE_IPSEC(_enable),
|
||||
TSIP_STACK_SET_NULL()) == 0);
|
||||
}
|
||||
|
||||
bool SipStack::setIPSecParameters(const char* algo, const char* ealgo, const char* mode, const char* proto)
|
||||
{
|
||||
return (tsip_stack_set(this->handle,
|
||||
return (tsip_stack_set(m_pHandle,
|
||||
TSIP_STACK_SET_IPSEC_PARAMS(algo, ealgo, mode, proto),
|
||||
TSIP_STACK_SET_NULL()) == 0);
|
||||
}
|
||||
|
||||
char* SipStack::dnsENUM(const char* service, const char* e164num, const char* domain)
|
||||
{
|
||||
tnet_dns_ctx_t* dnsctx = tsip_stack_get_dnsctx(this->handle);
|
||||
tnet_dns_ctx_t* dnsctx = tsip_stack_get_dnsctx(m_pHandle);
|
||||
char* uri = tsk_null;
|
||||
|
||||
if(dnsctx){
|
||||
|
@ -309,7 +309,7 @@ char* SipStack::dnsENUM(const char* service, const char* e164num, const char* do
|
|||
|
||||
char* SipStack::dnsNaptrSrv(const char* domain, const char* service, unsigned short *OUTPUT)
|
||||
{
|
||||
tnet_dns_ctx_t* dnsctx = tsip_stack_get_dnsctx(this->handle);
|
||||
tnet_dns_ctx_t* dnsctx = tsip_stack_get_dnsctx(m_pHandle);
|
||||
char* ip = tsk_null;
|
||||
tnet_port_t port;
|
||||
*OUTPUT = 0;
|
||||
|
@ -330,7 +330,7 @@ char* SipStack::dnsNaptrSrv(const char* domain, const char* service, unsigned sh
|
|||
|
||||
char* SipStack::dnsSrv(const char* service, unsigned short* OUTPUT)
|
||||
{
|
||||
tnet_dns_ctx_t* dnsctx = tsip_stack_get_dnsctx(this->handle);
|
||||
tnet_dns_ctx_t* dnsctx = tsip_stack_get_dnsctx(m_pHandle);
|
||||
char* ip = tsk_null;
|
||||
tnet_port_t port = 0;
|
||||
*OUTPUT = 0;
|
||||
|
@ -359,7 +359,7 @@ char* SipStack::getLocalIPnPort(const char* protocol, unsigned short* OUTPUT)
|
|||
return tsk_null;
|
||||
}
|
||||
|
||||
if((ret = tsip_stack_get_local_ip_n_port(this->handle, protocol, &port, &ip))){
|
||||
if((ret = tsip_stack_get_local_ip_n_port(m_pHandle, protocol, &port, &ip))){
|
||||
TSK_DEBUG_ERROR("Failed to get local ip and port with error code=%d", ret);
|
||||
return tsk_null;
|
||||
}
|
||||
|
@ -370,7 +370,7 @@ char* SipStack::getLocalIPnPort(const char* protocol, unsigned short* OUTPUT)
|
|||
|
||||
char* SipStack::getPreferredIdentity()
|
||||
{
|
||||
tsip_uri_t* ppid = tsip_stack_get_preferred_id(this->handle);
|
||||
tsip_uri_t* ppid = tsip_stack_get_preferred_id(m_pHandle);
|
||||
char* str_ppid = tsk_null;
|
||||
if(ppid){
|
||||
str_ppid = tsip_uri_tostring(ppid, tsk_false, tsk_false);
|
||||
|
@ -381,12 +381,12 @@ char* SipStack::getPreferredIdentity()
|
|||
|
||||
bool SipStack::isValid()
|
||||
{
|
||||
return (this->handle != tsk_null);
|
||||
return (m_pHandle != tsk_null);
|
||||
}
|
||||
|
||||
bool SipStack::stop()
|
||||
{
|
||||
int ret = tsip_stack_stop(this->handle);
|
||||
int ret = tsip_stack_stop(m_pHandle);
|
||||
return (ret == 0);
|
||||
}
|
||||
|
||||
|
@ -405,10 +405,10 @@ bool SipStack::isCodecSupported(tdav_codec_id_t codec)
|
|||
return tdav_codec_is_supported(codec) ? true : false;
|
||||
}
|
||||
|
||||
int stack_callback(const tsip_event_t *sipevent)
|
||||
static int stack_callback(const tsip_event_t *sipevent)
|
||||
{
|
||||
int ret = 0;
|
||||
const SipStack* Stack = tsk_null;
|
||||
const SipStack* sipStack = tsk_null;
|
||||
SipEvent* e = tsk_null;
|
||||
|
||||
if(!sipevent){ /* should never happen ...but who know? */
|
||||
|
@ -418,89 +418,89 @@ int stack_callback(const tsip_event_t *sipevent)
|
|||
else {
|
||||
if(sipevent->type == tsip_event_stack && sipevent->userdata){
|
||||
/* sessionless event */
|
||||
Stack = dyn_cast<const SipStack*>((const SipStack*)sipevent->userdata);
|
||||
sipStack = dyn_cast<const SipStack*>((const SipStack*)sipevent->userdata);
|
||||
}
|
||||
else {
|
||||
const void* userdata;
|
||||
/* gets the stack from the session */
|
||||
const tsip_stack_handle_t* stack_handle = tsip_ssession_get_stack(sipevent->ss);
|
||||
if(stack_handle && (userdata = tsip_stack_get_userdata(stack_handle))){
|
||||
Stack = dyn_cast<const SipStack*>((const SipStack*)userdata);
|
||||
sipStack = dyn_cast<const SipStack*>((const SipStack*)userdata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!Stack){
|
||||
if(!sipStack){
|
||||
TSK_DEBUG_WARN("Invalid SIP event (Stack is Null).");
|
||||
return -2;
|
||||
}
|
||||
|
||||
Stack->Lock();
|
||||
sipStack->Lock();
|
||||
|
||||
switch(sipevent->type){
|
||||
case tsip_event_register:
|
||||
{ /* REGISTER */
|
||||
if(Stack->getCallback()){
|
||||
if(sipStack->getCallback()){
|
||||
e = new RegistrationEvent(sipevent);
|
||||
Stack->getCallback()->OnRegistrationEvent((const RegistrationEvent*)e);
|
||||
sipStack->getCallback()->OnRegistrationEvent((const RegistrationEvent*)e);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case tsip_event_invite:
|
||||
{ /* INVITE */
|
||||
if(Stack->getCallback()){
|
||||
if(sipStack->getCallback()){
|
||||
e = new InviteEvent(sipevent);
|
||||
Stack->getCallback()->OnInviteEvent((const InviteEvent*)e);
|
||||
sipStack->getCallback()->OnInviteEvent((const InviteEvent*)e);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case tsip_event_message:
|
||||
{ /* MESSAGE */
|
||||
if(Stack->getCallback()){
|
||||
if(sipStack->getCallback()){
|
||||
e = new MessagingEvent(sipevent);
|
||||
Stack->getCallback()->OnMessagingEvent((const MessagingEvent*)e);
|
||||
sipStack->getCallback()->OnMessagingEvent((const MessagingEvent*)e);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case tsip_event_options:
|
||||
{ /* OPTIONS */
|
||||
if(Stack->getCallback()){
|
||||
if(sipStack->getCallback()){
|
||||
e = new OptionsEvent(sipevent);
|
||||
Stack->getCallback()->OnOptionsEvent((const OptionsEvent*)e);
|
||||
sipStack->getCallback()->OnOptionsEvent((const OptionsEvent*)e);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case tsip_event_publish:
|
||||
{ /* PUBLISH */
|
||||
if(Stack->getCallback()){
|
||||
if(sipStack->getCallback()){
|
||||
e = new PublicationEvent(sipevent);
|
||||
Stack->getCallback()->OnPublicationEvent((const PublicationEvent*)e);
|
||||
sipStack->getCallback()->OnPublicationEvent((const PublicationEvent*)e);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case tsip_event_subscribe:
|
||||
{ /* SUBSCRIBE */
|
||||
if(Stack->getCallback()){
|
||||
if(sipStack->getCallback()){
|
||||
e = new SubscriptionEvent(sipevent);
|
||||
Stack->getCallback()->OnSubscriptionEvent((const SubscriptionEvent*)e);
|
||||
sipStack->getCallback()->OnSubscriptionEvent((const SubscriptionEvent*)e);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case tsip_event_dialog:
|
||||
{ /* Common to all dialogs */
|
||||
if(Stack->getCallback()){
|
||||
if(sipStack->getCallback()){
|
||||
e = new DialogEvent(sipevent);
|
||||
Stack->getCallback()->OnDialogEvent((const DialogEvent*)e);
|
||||
sipStack->getCallback()->OnDialogEvent((const DialogEvent*)e);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case tsip_event_stack:
|
||||
{ /* Stack event */
|
||||
if(Stack->getCallback()){
|
||||
if(sipStack->getCallback()){
|
||||
e = new StackEvent(sipevent);
|
||||
Stack->getCallback()->OnStackEvent((const StackEvent*)e);
|
||||
sipStack->getCallback()->OnStackEvent((const StackEvent*)e);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -513,7 +513,7 @@ int stack_callback(const tsip_event_t *sipevent)
|
|||
}
|
||||
}
|
||||
|
||||
Stack->UnLock();
|
||||
sipStack->UnLock();
|
||||
|
||||
if(e){
|
||||
delete e;
|
||||
|
|
|
@ -33,12 +33,12 @@ class DDebugCallback;
|
|||
class SipStack: public SafeObject
|
||||
{
|
||||
public: /* ctor() and dtor() */
|
||||
SipStack(SipCallback* callback, const char* realm_uri, const char* impi_uri, const char* impu_uri);
|
||||
SipStack(SipCallback* pCallback, const char* realm_uri, const char* impi_uri, const char* impu_uri);
|
||||
~SipStack();
|
||||
|
||||
public: /* API functions */
|
||||
bool start();
|
||||
bool setDebugCallback(DDebugCallback* callback);
|
||||
bool setDebugCallback(DDebugCallback* pCallback);
|
||||
bool setRealm(const char* realm_uri);
|
||||
bool setIMPI(const char* impi);
|
||||
bool setIMPU(const char* impu_uri);
|
||||
|
@ -88,20 +88,20 @@ public: /* API functions */
|
|||
public: /* Public helper function */
|
||||
#if !defined(SWIG)
|
||||
inline tsip_stack_handle_t* getHandle()const{
|
||||
return this->handle;
|
||||
return m_pHandle;
|
||||
}
|
||||
inline SipCallback* getCallback()const{
|
||||
return this->callback;
|
||||
return m_pCallback;
|
||||
}
|
||||
inline DDebugCallback* getDebugCallback() const{
|
||||
return this->debugCallback;
|
||||
return m_pDebugCallback;
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
SipCallback* callback;
|
||||
DDebugCallback* debugCallback;
|
||||
tsip_stack_handle_t *handle;
|
||||
SipCallback* m_pCallback;
|
||||
DDebugCallback* m_pDebugCallback;
|
||||
tsip_stack_handle_t* m_pHandle;
|
||||
|
||||
static unsigned count;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,424 @@
|
|||
/* Copyright (C) 2002-2006 Jean-Marc Valin*/
|
||||
/**
|
||||
@file speex.h
|
||||
@brief Describes the different modes of the codec
|
||||
*/
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of the Xiph.org Foundation nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef SPEEX_H
|
||||
#define SPEEX_H
|
||||
/** @defgroup Codec Speex encoder and decoder
|
||||
* This is the Speex codec itself.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "speex/speex_bits.h"
|
||||
#include "speex/speex_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Values allowed for *ctl() requests */
|
||||
|
||||
/** Set enhancement on/off (decoder only) */
|
||||
#define SPEEX_SET_ENH 0
|
||||
/** Get enhancement state (decoder only) */
|
||||
#define SPEEX_GET_ENH 1
|
||||
|
||||
/*Would be SPEEX_SET_FRAME_SIZE, but it's (currently) invalid*/
|
||||
/** Obtain frame size used by encoder/decoder */
|
||||
#define SPEEX_GET_FRAME_SIZE 3
|
||||
|
||||
/** Set quality value */
|
||||
#define SPEEX_SET_QUALITY 4
|
||||
/** Get current quality setting */
|
||||
/* #define SPEEX_GET_QUALITY 5 -- Doesn't make much sense, does it? */
|
||||
|
||||
/** Set sub-mode to use */
|
||||
#define SPEEX_SET_MODE 6
|
||||
/** Get current sub-mode in use */
|
||||
#define SPEEX_GET_MODE 7
|
||||
|
||||
/** Set low-band sub-mode to use (wideband only)*/
|
||||
#define SPEEX_SET_LOW_MODE 8
|
||||
/** Get current low-band mode in use (wideband only)*/
|
||||
#define SPEEX_GET_LOW_MODE 9
|
||||
|
||||
/** Set high-band sub-mode to use (wideband only)*/
|
||||
#define SPEEX_SET_HIGH_MODE 10
|
||||
/** Get current high-band mode in use (wideband only)*/
|
||||
#define SPEEX_GET_HIGH_MODE 11
|
||||
|
||||
/** Set VBR on (1) or off (0) */
|
||||
#define SPEEX_SET_VBR 12
|
||||
/** Get VBR status (1 for on, 0 for off) */
|
||||
#define SPEEX_GET_VBR 13
|
||||
|
||||
/** Set quality value for VBR encoding (0-10) */
|
||||
#define SPEEX_SET_VBR_QUALITY 14
|
||||
/** Get current quality value for VBR encoding (0-10) */
|
||||
#define SPEEX_GET_VBR_QUALITY 15
|
||||
|
||||
/** Set complexity of the encoder (0-10) */
|
||||
#define SPEEX_SET_COMPLEXITY 16
|
||||
/** Get current complexity of the encoder (0-10) */
|
||||
#define SPEEX_GET_COMPLEXITY 17
|
||||
|
||||
/** Set bit-rate used by the encoder (or lower) */
|
||||
#define SPEEX_SET_BITRATE 18
|
||||
/** Get current bit-rate used by the encoder or decoder */
|
||||
#define SPEEX_GET_BITRATE 19
|
||||
|
||||
/** Define a handler function for in-band Speex request*/
|
||||
#define SPEEX_SET_HANDLER 20
|
||||
|
||||
/** Define a handler function for in-band user-defined request*/
|
||||
#define SPEEX_SET_USER_HANDLER 22
|
||||
|
||||
/** Set sampling rate used in bit-rate computation */
|
||||
#define SPEEX_SET_SAMPLING_RATE 24
|
||||
/** Get sampling rate used in bit-rate computation */
|
||||
#define SPEEX_GET_SAMPLING_RATE 25
|
||||
|
||||
/** Reset the encoder/decoder memories to zero*/
|
||||
#define SPEEX_RESET_STATE 26
|
||||
|
||||
/** Get VBR info (mostly used internally) */
|
||||
#define SPEEX_GET_RELATIVE_QUALITY 29
|
||||
|
||||
/** Set VAD status (1 for on, 0 for off) */
|
||||
#define SPEEX_SET_VAD 30
|
||||
|
||||
/** Get VAD status (1 for on, 0 for off) */
|
||||
#define SPEEX_GET_VAD 31
|
||||
|
||||
/** Set Average Bit-Rate (ABR) to n bits per seconds */
|
||||
#define SPEEX_SET_ABR 32
|
||||
/** Get Average Bit-Rate (ABR) setting (in bps) */
|
||||
#define SPEEX_GET_ABR 33
|
||||
|
||||
/** Set DTX status (1 for on, 0 for off) */
|
||||
#define SPEEX_SET_DTX 34
|
||||
/** Get DTX status (1 for on, 0 for off) */
|
||||
#define SPEEX_GET_DTX 35
|
||||
|
||||
/** Set submode encoding in each frame (1 for yes, 0 for no, setting to no breaks the standard) */
|
||||
#define SPEEX_SET_SUBMODE_ENCODING 36
|
||||
/** Get submode encoding in each frame */
|
||||
#define SPEEX_GET_SUBMODE_ENCODING 37
|
||||
|
||||
/*#define SPEEX_SET_LOOKAHEAD 38*/
|
||||
/** Returns the lookahead used by Speex */
|
||||
#define SPEEX_GET_LOOKAHEAD 39
|
||||
|
||||
/** Sets tuning for packet-loss concealment (expected loss rate) */
|
||||
#define SPEEX_SET_PLC_TUNING 40
|
||||
/** Gets tuning for PLC */
|
||||
#define SPEEX_GET_PLC_TUNING 41
|
||||
|
||||
/** Sets the max bit-rate allowed in VBR mode */
|
||||
#define SPEEX_SET_VBR_MAX_BITRATE 42
|
||||
/** Gets the max bit-rate allowed in VBR mode */
|
||||
#define SPEEX_GET_VBR_MAX_BITRATE 43
|
||||
|
||||
/** Turn on/off input/output high-pass filtering */
|
||||
#define SPEEX_SET_HIGHPASS 44
|
||||
/** Get status of input/output high-pass filtering */
|
||||
#define SPEEX_GET_HIGHPASS 45
|
||||
|
||||
/** Get "activity level" of the last decoded frame, i.e.
|
||||
how much damage we cause if we remove the frame */
|
||||
#define SPEEX_GET_ACTIVITY 47
|
||||
|
||||
|
||||
/* Preserving compatibility:*/
|
||||
/** Equivalent to SPEEX_SET_ENH */
|
||||
#define SPEEX_SET_PF 0
|
||||
/** Equivalent to SPEEX_GET_ENH */
|
||||
#define SPEEX_GET_PF 1
|
||||
|
||||
|
||||
|
||||
|
||||
/* Values allowed for mode queries */
|
||||
/** Query the frame size of a mode */
|
||||
#define SPEEX_MODE_FRAME_SIZE 0
|
||||
|
||||
/** Query the size of an encoded frame for a particular sub-mode */
|
||||
#define SPEEX_SUBMODE_BITS_PER_FRAME 1
|
||||
|
||||
|
||||
|
||||
/** Get major Speex version */
|
||||
#define SPEEX_LIB_GET_MAJOR_VERSION 1
|
||||
/** Get minor Speex version */
|
||||
#define SPEEX_LIB_GET_MINOR_VERSION 3
|
||||
/** Get micro Speex version */
|
||||
#define SPEEX_LIB_GET_MICRO_VERSION 5
|
||||
/** Get extra Speex version */
|
||||
#define SPEEX_LIB_GET_EXTRA_VERSION 7
|
||||
/** Get Speex version string */
|
||||
#define SPEEX_LIB_GET_VERSION_STRING 9
|
||||
|
||||
/*#define SPEEX_LIB_SET_ALLOC_FUNC 10
|
||||
#define SPEEX_LIB_GET_ALLOC_FUNC 11
|
||||
#define SPEEX_LIB_SET_FREE_FUNC 12
|
||||
#define SPEEX_LIB_GET_FREE_FUNC 13
|
||||
|
||||
#define SPEEX_LIB_SET_WARNING_FUNC 14
|
||||
#define SPEEX_LIB_GET_WARNING_FUNC 15
|
||||
#define SPEEX_LIB_SET_ERROR_FUNC 16
|
||||
#define SPEEX_LIB_GET_ERROR_FUNC 17
|
||||
*/
|
||||
|
||||
/** Number of defined modes in Speex */
|
||||
#define SPEEX_NB_MODES 3
|
||||
|
||||
/** modeID for the defined narrowband mode */
|
||||
#define SPEEX_MODEID_NB 0
|
||||
|
||||
/** modeID for the defined wideband mode */
|
||||
#define SPEEX_MODEID_WB 1
|
||||
|
||||
/** modeID for the defined ultra-wideband mode */
|
||||
#define SPEEX_MODEID_UWB 2
|
||||
|
||||
struct SpeexMode;
|
||||
|
||||
|
||||
/* Prototypes for mode function pointers */
|
||||
|
||||
/** Encoder state initialization function */
|
||||
typedef void *(*encoder_init_func)(const struct SpeexMode *mode);
|
||||
|
||||
/** Encoder state destruction function */
|
||||
typedef void (*encoder_destroy_func)(void *st);
|
||||
|
||||
/** Main encoding function */
|
||||
typedef int (*encode_func)(void *state, void *in, SpeexBits *bits);
|
||||
|
||||
/** Function for controlling the encoder options */
|
||||
typedef int (*encoder_ctl_func)(void *state, int request, void *ptr);
|
||||
|
||||
/** Decoder state initialization function */
|
||||
typedef void *(*decoder_init_func)(const struct SpeexMode *mode);
|
||||
|
||||
/** Decoder state destruction function */
|
||||
typedef void (*decoder_destroy_func)(void *st);
|
||||
|
||||
/** Main decoding function */
|
||||
typedef int (*decode_func)(void *state, SpeexBits *bits, void *out);
|
||||
|
||||
/** Function for controlling the decoder options */
|
||||
typedef int (*decoder_ctl_func)(void *state, int request, void *ptr);
|
||||
|
||||
|
||||
/** Query function for a mode */
|
||||
typedef int (*mode_query_func)(const void *mode, int request, void *ptr);
|
||||
|
||||
/** Struct defining a Speex mode */
|
||||
typedef struct SpeexMode {
|
||||
/** Pointer to the low-level mode data */
|
||||
const void *mode;
|
||||
|
||||
/** Pointer to the mode query function */
|
||||
mode_query_func query;
|
||||
|
||||
/** The name of the mode (you should not rely on this to identify the mode)*/
|
||||
const char *modeName;
|
||||
|
||||
/**ID of the mode*/
|
||||
int modeID;
|
||||
|
||||
/**Version number of the bitstream (incremented every time we break
|
||||
bitstream compatibility*/
|
||||
int bitstream_version;
|
||||
|
||||
/** Pointer to encoder initialization function */
|
||||
encoder_init_func enc_init;
|
||||
|
||||
/** Pointer to encoder destruction function */
|
||||
encoder_destroy_func enc_destroy;
|
||||
|
||||
/** Pointer to frame encoding function */
|
||||
encode_func enc;
|
||||
|
||||
/** Pointer to decoder initialization function */
|
||||
decoder_init_func dec_init;
|
||||
|
||||
/** Pointer to decoder destruction function */
|
||||
decoder_destroy_func dec_destroy;
|
||||
|
||||
/** Pointer to frame decoding function */
|
||||
decode_func dec;
|
||||
|
||||
/** ioctl-like requests for encoder */
|
||||
encoder_ctl_func enc_ctl;
|
||||
|
||||
/** ioctl-like requests for decoder */
|
||||
decoder_ctl_func dec_ctl;
|
||||
|
||||
} SpeexMode;
|
||||
|
||||
/**
|
||||
* Returns a handle to a newly created Speex encoder state structure. For now,
|
||||
* the "mode" argument can be &nb_mode or &wb_mode . In the future, more modes
|
||||
* may be added. Note that for now if you have more than one channels to
|
||||
* encode, you need one state per channel.
|
||||
*
|
||||
* @param mode The mode to use (either speex_nb_mode or speex_wb.mode)
|
||||
* @return A newly created encoder state or NULL if state allocation fails
|
||||
*/
|
||||
void *speex_encoder_init(const SpeexMode *mode);
|
||||
|
||||
/** Frees all resources associated to an existing Speex encoder state.
|
||||
* @param state Encoder state to be destroyed */
|
||||
void speex_encoder_destroy(void *state);
|
||||
|
||||
/** Uses an existing encoder state to encode one frame of speech pointed to by
|
||||
"in". The encoded bit-stream is saved in "bits".
|
||||
@param state Encoder state
|
||||
@param in Frame that will be encoded with a +-2^15 range. This data MAY be
|
||||
overwritten by the encoder and should be considered uninitialised
|
||||
after the call.
|
||||
@param bits Bit-stream where the data will be written
|
||||
@return 0 if frame needs not be transmitted (DTX only), 1 otherwise
|
||||
*/
|
||||
int speex_encode(void *state, float *in, SpeexBits *bits);
|
||||
|
||||
/** Uses an existing encoder state to encode one frame of speech pointed to by
|
||||
"in". The encoded bit-stream is saved in "bits".
|
||||
@param state Encoder state
|
||||
@param in Frame that will be encoded with a +-2^15 range
|
||||
@param bits Bit-stream where the data will be written
|
||||
@return 0 if frame needs not be transmitted (DTX only), 1 otherwise
|
||||
*/
|
||||
int speex_encode_int(void *state, spx_int16_t *in, SpeexBits *bits);
|
||||
|
||||
/** Used like the ioctl function to control the encoder parameters
|
||||
*
|
||||
* @param state Encoder state
|
||||
* @param request ioctl-type request (one of the SPEEX_* macros)
|
||||
* @param ptr Data exchanged to-from function
|
||||
* @return 0 if no error, -1 if request in unknown, -2 for invalid parameter
|
||||
*/
|
||||
int speex_encoder_ctl(void *state, int request, void *ptr);
|
||||
|
||||
|
||||
/** Returns a handle to a newly created decoder state structure. For now,
|
||||
* the mode argument can be &nb_mode or &wb_mode . In the future, more modes
|
||||
* may be added. Note that for now if you have more than one channels to
|
||||
* decode, you need one state per channel.
|
||||
*
|
||||
* @param mode Speex mode (one of speex_nb_mode or speex_wb_mode)
|
||||
* @return A newly created decoder state or NULL if state allocation fails
|
||||
*/
|
||||
void *speex_decoder_init(const SpeexMode *mode);
|
||||
|
||||
/** Frees all resources associated to an existing decoder state.
|
||||
*
|
||||
* @param state State to be destroyed
|
||||
*/
|
||||
void speex_decoder_destroy(void *state);
|
||||
|
||||
/** Uses an existing decoder state to decode one frame of speech from
|
||||
* bit-stream bits. The output speech is saved written to out.
|
||||
*
|
||||
* @param state Decoder state
|
||||
* @param bits Bit-stream from which to decode the frame (NULL if the packet was lost)
|
||||
* @param out Where to write the decoded frame
|
||||
* @return return status (0 for no error, -1 for end of stream, -2 corrupt stream)
|
||||
*/
|
||||
int speex_decode(void *state, SpeexBits *bits, float *out);
|
||||
|
||||
/** Uses an existing decoder state to decode one frame of speech from
|
||||
* bit-stream bits. The output speech is saved written to out.
|
||||
*
|
||||
* @param state Decoder state
|
||||
* @param bits Bit-stream from which to decode the frame (NULL if the packet was lost)
|
||||
* @param out Where to write the decoded frame
|
||||
* @return return status (0 for no error, -1 for end of stream, -2 corrupt stream)
|
||||
*/
|
||||
int speex_decode_int(void *state, SpeexBits *bits, spx_int16_t *out);
|
||||
|
||||
/** Used like the ioctl function to control the encoder parameters
|
||||
*
|
||||
* @param state Decoder state
|
||||
* @param request ioctl-type request (one of the SPEEX_* macros)
|
||||
* @param ptr Data exchanged to-from function
|
||||
* @return 0 if no error, -1 if request in unknown, -2 for invalid parameter
|
||||
*/
|
||||
int speex_decoder_ctl(void *state, int request, void *ptr);
|
||||
|
||||
|
||||
/** Query function for mode information
|
||||
*
|
||||
* @param mode Speex mode
|
||||
* @param request ioctl-type request (one of the SPEEX_* macros)
|
||||
* @param ptr Data exchanged to-from function
|
||||
* @return 0 if no error, -1 if request in unknown, -2 for invalid parameter
|
||||
*/
|
||||
int speex_mode_query(const SpeexMode *mode, int request, void *ptr);
|
||||
|
||||
/** Functions for controlling the behavior of libspeex
|
||||
* @param request ioctl-type request (one of the SPEEX_LIB_* macros)
|
||||
* @param ptr Data exchanged to-from function
|
||||
* @return 0 if no error, -1 if request in unknown, -2 for invalid parameter
|
||||
*/
|
||||
int speex_lib_ctl(int request, void *ptr);
|
||||
|
||||
/** Default narrowband mode */
|
||||
extern const SpeexMode speex_nb_mode;
|
||||
|
||||
/** Default wideband mode */
|
||||
extern const SpeexMode speex_wb_mode;
|
||||
|
||||
/** Default "ultra-wideband" mode */
|
||||
extern const SpeexMode speex_uwb_mode;
|
||||
|
||||
/** List of all modes available */
|
||||
extern const SpeexMode * const speex_mode_list[SPEEX_NB_MODES];
|
||||
|
||||
/** Obtain one of the modes available */
|
||||
const SpeexMode * speex_lib_get_mode (int mode);
|
||||
|
||||
#ifndef WIN32
|
||||
/* We actually override the function in the narrowband case so that we can avoid linking in the wideband stuff */
|
||||
#define speex_lib_get_mode(mode) ((mode)==SPEEX_MODEID_NB ? &speex_nb_mode : speex_lib_get_mode (mode))
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @}*/
|
||||
#endif
|
|
@ -0,0 +1,174 @@
|
|||
/* Copyright (C) 2002 Jean-Marc Valin */
|
||||
/**
|
||||
@file speex_bits.h
|
||||
@brief Handles bit packing/unpacking
|
||||
*/
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of the Xiph.org Foundation nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef BITS_H
|
||||
#define BITS_H
|
||||
/** @defgroup SpeexBits SpeexBits: Bit-stream manipulations
|
||||
* This is the structure that holds the bit-stream when encoding or decoding
|
||||
* with Speex. It allows some manipulations as well.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Bit-packing data structure representing (part of) a bit-stream. */
|
||||
typedef struct SpeexBits {
|
||||
char *chars; /**< "raw" data */
|
||||
int nbBits; /**< Total number of bits stored in the stream*/
|
||||
int charPtr; /**< Position of the byte "cursor" */
|
||||
int bitPtr; /**< Position of the bit "cursor" within the current char */
|
||||
int owner; /**< Does the struct "own" the "raw" buffer (member "chars") */
|
||||
int overflow;/**< Set to one if we try to read past the valid data */
|
||||
int buf_size;/**< Allocated size for buffer */
|
||||
int reserved1; /**< Reserved for future use */
|
||||
void *reserved2; /**< Reserved for future use */
|
||||
} SpeexBits;
|
||||
|
||||
/** Initializes and allocates resources for a SpeexBits struct */
|
||||
void speex_bits_init(SpeexBits *bits);
|
||||
|
||||
/** Initializes SpeexBits struct using a pre-allocated buffer*/
|
||||
void speex_bits_init_buffer(SpeexBits *bits, void *buff, int buf_size);
|
||||
|
||||
/** Sets the bits in a SpeexBits struct to use data from an existing buffer (for decoding without copying data) */
|
||||
void speex_bits_set_bit_buffer(SpeexBits *bits, void *buff, int buf_size);
|
||||
|
||||
/** Frees all resources associated to a SpeexBits struct. Right now this does nothing since no resources are allocated, but this could change in the future.*/
|
||||
void speex_bits_destroy(SpeexBits *bits);
|
||||
|
||||
/** Resets bits to initial value (just after initialization, erasing content)*/
|
||||
void speex_bits_reset(SpeexBits *bits);
|
||||
|
||||
/** Rewind the bit-stream to the beginning (ready for read) without erasing the content */
|
||||
void speex_bits_rewind(SpeexBits *bits);
|
||||
|
||||
/** Initializes the bit-stream from the data in an area of memory */
|
||||
void speex_bits_read_from(SpeexBits *bits, char *bytes, int len);
|
||||
|
||||
/** Append bytes to the bit-stream
|
||||
*
|
||||
* @param bits Bit-stream to operate on
|
||||
* @param bytes pointer to the bytes what will be appended
|
||||
* @param len Number of bytes of append
|
||||
*/
|
||||
void speex_bits_read_whole_bytes(SpeexBits *bits, char *bytes, int len);
|
||||
|
||||
/** Write the content of a bit-stream to an area of memory
|
||||
*
|
||||
* @param bits Bit-stream to operate on
|
||||
* @param bytes Memory location where to write the bits
|
||||
* @param max_len Maximum number of bytes to write (i.e. size of the "bytes" buffer)
|
||||
* @return Number of bytes written to the "bytes" buffer
|
||||
*/
|
||||
int speex_bits_write(SpeexBits *bits, char *bytes, int max_len);
|
||||
|
||||
/** Like speex_bits_write, but writes only the complete bytes in the stream. Also removes the written bytes from the stream */
|
||||
int speex_bits_write_whole_bytes(SpeexBits *bits, char *bytes, int max_len);
|
||||
|
||||
/** Append bits to the bit-stream
|
||||
* @param bits Bit-stream to operate on
|
||||
* @param data Value to append as integer
|
||||
* @param nbBits number of bits to consider in "data"
|
||||
*/
|
||||
void speex_bits_pack(SpeexBits *bits, int data, int nbBits);
|
||||
|
||||
/** Interpret the next bits in the bit-stream as a signed integer
|
||||
*
|
||||
* @param bits Bit-stream to operate on
|
||||
* @param nbBits Number of bits to interpret
|
||||
* @return A signed integer represented by the bits read
|
||||
*/
|
||||
int speex_bits_unpack_signed(SpeexBits *bits, int nbBits);
|
||||
|
||||
/** Interpret the next bits in the bit-stream as an unsigned integer
|
||||
*
|
||||
* @param bits Bit-stream to operate on
|
||||
* @param nbBits Number of bits to interpret
|
||||
* @return An unsigned integer represented by the bits read
|
||||
*/
|
||||
unsigned int speex_bits_unpack_unsigned(SpeexBits *bits, int nbBits);
|
||||
|
||||
/** Returns the number of bytes in the bit-stream, including the last one even if it is not "full"
|
||||
*
|
||||
* @param bits Bit-stream to operate on
|
||||
* @return Number of bytes in the stream
|
||||
*/
|
||||
int speex_bits_nbytes(SpeexBits *bits);
|
||||
|
||||
/** Same as speex_bits_unpack_unsigned, but without modifying the cursor position
|
||||
*
|
||||
* @param bits Bit-stream to operate on
|
||||
* @param nbBits Number of bits to look for
|
||||
* @return Value of the bits peeked, interpreted as unsigned
|
||||
*/
|
||||
unsigned int speex_bits_peek_unsigned(SpeexBits *bits, int nbBits);
|
||||
|
||||
/** Get the value of the next bit in the stream, without modifying the
|
||||
* "cursor" position
|
||||
*
|
||||
* @param bits Bit-stream to operate on
|
||||
* @return Value of the bit peeked (one bit only)
|
||||
*/
|
||||
int speex_bits_peek(SpeexBits *bits);
|
||||
|
||||
/** Advances the position of the "bit cursor" in the stream
|
||||
*
|
||||
* @param bits Bit-stream to operate on
|
||||
* @param n Number of bits to advance
|
||||
*/
|
||||
void speex_bits_advance(SpeexBits *bits, int n);
|
||||
|
||||
/** Returns the number of bits remaining to be read in a stream
|
||||
*
|
||||
* @param bits Bit-stream to operate on
|
||||
* @return Number of bits that can still be read from the stream
|
||||
*/
|
||||
int speex_bits_remaining(SpeexBits *bits);
|
||||
|
||||
/** Insert a terminator so that the data can be sent as a packet while auto-detecting
|
||||
* the number of frames in each packet
|
||||
*
|
||||
* @param bits Bit-stream to operate on
|
||||
*/
|
||||
void speex_bits_insert_terminator(SpeexBits *bits);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* @} */
|
||||
#endif
|
|
@ -0,0 +1,68 @@
|
|||
/* Copyright (C) 2007 Jean-Marc Valin
|
||||
|
||||
File: speex_buffer.h
|
||||
This is a very simple ring buffer implementation. It is not thread-safe
|
||||
so you need to do your own locking.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SPEEX_BUFFER_H
|
||||
#define SPEEX_BUFFER_H
|
||||
|
||||
#include "speex/speex_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct SpeexBuffer_;
|
||||
typedef struct SpeexBuffer_ SpeexBuffer;
|
||||
|
||||
SpeexBuffer *speex_buffer_init(int size);
|
||||
|
||||
void speex_buffer_destroy(SpeexBuffer *st);
|
||||
|
||||
int speex_buffer_write(SpeexBuffer *st, void *data, int len);
|
||||
|
||||
int speex_buffer_writezeros(SpeexBuffer *st, int len);
|
||||
|
||||
int speex_buffer_read(SpeexBuffer *st, void *data, int len);
|
||||
|
||||
int speex_buffer_get_available(SpeexBuffer *st);
|
||||
|
||||
int speex_buffer_resize(SpeexBuffer *st, int len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
/* Copyright (C) 2002 Jean-Marc Valin*/
|
||||
/**
|
||||
@file speex_callbacks.h
|
||||
@brief Describes callback handling and in-band signalling
|
||||
*/
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of the Xiph.org Foundation nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef SPEEX_CALLBACKS_H
|
||||
#define SPEEX_CALLBACKS_H
|
||||
/** @defgroup SpeexCallbacks Various definitions for Speex callbacks supported by the decoder.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "speex.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Total number of callbacks */
|
||||
#define SPEEX_MAX_CALLBACKS 16
|
||||
|
||||
/* Describes all the in-band requests */
|
||||
|
||||
/*These are 1-bit requests*/
|
||||
/** Request for perceptual enhancement (1 for on, 0 for off) */
|
||||
#define SPEEX_INBAND_ENH_REQUEST 0
|
||||
/** Reserved */
|
||||
#define SPEEX_INBAND_RESERVED1 1
|
||||
|
||||
/*These are 4-bit requests*/
|
||||
/** Request for a mode change */
|
||||
#define SPEEX_INBAND_MODE_REQUEST 2
|
||||
/** Request for a low mode change */
|
||||
#define SPEEX_INBAND_LOW_MODE_REQUEST 3
|
||||
/** Request for a high mode change */
|
||||
#define SPEEX_INBAND_HIGH_MODE_REQUEST 4
|
||||
/** Request for VBR (1 on, 0 off) */
|
||||
#define SPEEX_INBAND_VBR_QUALITY_REQUEST 5
|
||||
/** Request to be sent acknowledge */
|
||||
#define SPEEX_INBAND_ACKNOWLEDGE_REQUEST 6
|
||||
/** Request for VBR (1 for on, 0 for off) */
|
||||
#define SPEEX_INBAND_VBR_REQUEST 7
|
||||
|
||||
/*These are 8-bit requests*/
|
||||
/** Send a character in-band */
|
||||
#define SPEEX_INBAND_CHAR 8
|
||||
/** Intensity stereo information */
|
||||
#define SPEEX_INBAND_STEREO 9
|
||||
|
||||
/*These are 16-bit requests*/
|
||||
/** Transmit max bit-rate allowed */
|
||||
#define SPEEX_INBAND_MAX_BITRATE 10
|
||||
|
||||
/*These are 32-bit requests*/
|
||||
/** Acknowledge packet reception */
|
||||
#define SPEEX_INBAND_ACKNOWLEDGE 12
|
||||
|
||||
/** Callback function type */
|
||||
typedef int (*speex_callback_func)(SpeexBits *bits, void *state, void *data);
|
||||
|
||||
/** Callback information */
|
||||
typedef struct SpeexCallback {
|
||||
int callback_id; /**< ID associated to the callback */
|
||||
speex_callback_func func; /**< Callback handler function */
|
||||
void *data; /**< Data that will be sent to the handler */
|
||||
void *reserved1; /**< Reserved for future use */
|
||||
int reserved2; /**< Reserved for future use */
|
||||
} SpeexCallback;
|
||||
|
||||
/** Handle in-band request */
|
||||
int speex_inband_handler(SpeexBits *bits, SpeexCallback *callback_list, void *state);
|
||||
|
||||
/** Standard handler for mode request (change mode, no questions asked) */
|
||||
int speex_std_mode_request_handler(SpeexBits *bits, void *state, void *data);
|
||||
|
||||
/** Standard handler for high mode request (change high mode, no questions asked) */
|
||||
int speex_std_high_mode_request_handler(SpeexBits *bits, void *state, void *data);
|
||||
|
||||
/** Standard handler for in-band characters (write to stderr) */
|
||||
int speex_std_char_handler(SpeexBits *bits, void *state, void *data);
|
||||
|
||||
/** Default handler for user-defined requests: in this case, just ignore */
|
||||
int speex_default_user_handler(SpeexBits *bits, void *state, void *data);
|
||||
|
||||
|
||||
|
||||
/** Standard handler for low mode request (change low mode, no questions asked) */
|
||||
int speex_std_low_mode_request_handler(SpeexBits *bits, void *state, void *data);
|
||||
|
||||
/** Standard handler for VBR request (Set VBR, no questions asked) */
|
||||
int speex_std_vbr_request_handler(SpeexBits *bits, void *state, void *data);
|
||||
|
||||
/** Standard handler for enhancer request (Turn enhancer on/off, no questions asked) */
|
||||
int speex_std_enh_request_handler(SpeexBits *bits, void *state, void *data);
|
||||
|
||||
/** Standard handler for VBR quality request (Set VBR quality, no questions asked) */
|
||||
int speex_std_vbr_quality_request_handler(SpeexBits *bits, void *state, void *data);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
#endif
|
|
@ -0,0 +1,170 @@
|
|||
/* Copyright (C) Jean-Marc Valin */
|
||||
/**
|
||||
@file speex_echo.h
|
||||
@brief Echo cancellation
|
||||
*/
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SPEEX_ECHO_H
|
||||
#define SPEEX_ECHO_H
|
||||
/** @defgroup SpeexEchoState SpeexEchoState: Acoustic echo canceller
|
||||
* This is the acoustic echo canceller module.
|
||||
* @{
|
||||
*/
|
||||
#include "speex/speex_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Obtain frame size used by the AEC */
|
||||
#define SPEEX_ECHO_GET_FRAME_SIZE 3
|
||||
|
||||
/** Set sampling rate */
|
||||
#define SPEEX_ECHO_SET_SAMPLING_RATE 24
|
||||
/** Get sampling rate */
|
||||
#define SPEEX_ECHO_GET_SAMPLING_RATE 25
|
||||
|
||||
/* Can't set window sizes */
|
||||
/** Get size of impulse response (int32) */
|
||||
#define SPEEX_ECHO_GET_IMPULSE_RESPONSE_SIZE 27
|
||||
|
||||
/* Can't set window content */
|
||||
/** Get impulse response (int32[]) */
|
||||
#define SPEEX_ECHO_GET_IMPULSE_RESPONSE 29
|
||||
|
||||
/** Internal echo canceller state. Should never be accessed directly. */
|
||||
struct SpeexEchoState_;
|
||||
|
||||
/** @class SpeexEchoState
|
||||
* This holds the state of the echo canceller. You need one per channel.
|
||||
*/
|
||||
|
||||
/** Internal echo canceller state. Should never be accessed directly. */
|
||||
typedef struct SpeexEchoState_ SpeexEchoState;
|
||||
|
||||
/** Creates a new echo canceller state
|
||||
* @param frame_size Number of samples to process at one time (should correspond to 10-20 ms)
|
||||
* @param filter_length Number of samples of echo to cancel (should generally correspond to 100-500 ms)
|
||||
* @return Newly-created echo canceller state
|
||||
*/
|
||||
SpeexEchoState *speex_echo_state_init(int frame_size, int filter_length);
|
||||
|
||||
/** Creates a new multi-channel echo canceller state
|
||||
* @param frame_size Number of samples to process at one time (should correspond to 10-20 ms)
|
||||
* @param filter_length Number of samples of echo to cancel (should generally correspond to 100-500 ms)
|
||||
* @param nb_mic Number of microphone channels
|
||||
* @param nb_speakers Number of speaker channels
|
||||
* @return Newly-created echo canceller state
|
||||
*/
|
||||
SpeexEchoState *speex_echo_state_init_mc(int frame_size, int filter_length, int nb_mic, int nb_speakers);
|
||||
|
||||
/** Destroys an echo canceller state
|
||||
* @param st Echo canceller state
|
||||
*/
|
||||
void speex_echo_state_destroy(SpeexEchoState *st);
|
||||
|
||||
/** Performs echo cancellation a frame, based on the audio sent to the speaker (no delay is added
|
||||
* to playback in this form)
|
||||
*
|
||||
* @param st Echo canceller state
|
||||
* @param rec Signal from the microphone (near end + far end echo)
|
||||
* @param play Signal played to the speaker (received from far end)
|
||||
* @param out Returns near-end signal with echo removed
|
||||
*/
|
||||
void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *rec, const spx_int16_t *play, spx_int16_t *out);
|
||||
|
||||
/** Performs echo cancellation a frame (deprecated) */
|
||||
void speex_echo_cancel(SpeexEchoState *st, const spx_int16_t *rec, const spx_int16_t *play, spx_int16_t *out, spx_int32_t *Yout);
|
||||
|
||||
/** Perform echo cancellation using internal playback buffer, which is delayed by two frames
|
||||
* to account for the delay introduced by most soundcards (but it could be off!)
|
||||
* @param st Echo canceller state
|
||||
* @param rec Signal from the microphone (near end + far end echo)
|
||||
* @param out Returns near-end signal with echo removed
|
||||
*/
|
||||
void speex_echo_capture(SpeexEchoState *st, const spx_int16_t *rec, spx_int16_t *out);
|
||||
|
||||
/** Let the echo canceller know that a frame was just queued to the soundcard
|
||||
* @param st Echo canceller state
|
||||
* @param play Signal played to the speaker (received from far end)
|
||||
*/
|
||||
void speex_echo_playback(SpeexEchoState *st, const spx_int16_t *play);
|
||||
|
||||
/** Reset the echo canceller to its original state
|
||||
* @param st Echo canceller state
|
||||
*/
|
||||
void speex_echo_state_reset(SpeexEchoState *st);
|
||||
|
||||
/** Used like the ioctl function to control the echo canceller parameters
|
||||
*
|
||||
* @param st Echo canceller state
|
||||
* @param request ioctl-type request (one of the SPEEX_ECHO_* macros)
|
||||
* @param ptr Data exchanged to-from function
|
||||
* @return 0 if no error, -1 if request in unknown
|
||||
*/
|
||||
int speex_echo_ctl(SpeexEchoState *st, int request, void *ptr);
|
||||
|
||||
|
||||
|
||||
struct SpeexDecorrState_;
|
||||
|
||||
typedef struct SpeexDecorrState_ SpeexDecorrState;
|
||||
|
||||
|
||||
/** Create a state for the channel decorrelation algorithm
|
||||
This is useful for multi-channel echo cancellation only
|
||||
* @param rate Sampling rate
|
||||
* @param channels Number of channels (it's a bit pointless if you don't have at least 2)
|
||||
* @param frame_size Size of the frame to process at ones (counting samples *per* channel)
|
||||
*/
|
||||
SpeexDecorrState *speex_decorrelate_new(int rate, int channels, int frame_size);
|
||||
|
||||
/** Remove correlation between the channels by modifying the phase and possibly
|
||||
adding noise in a way that is not (or little) perceptible.
|
||||
* @param st Decorrelator state
|
||||
* @param in Input audio in interleaved format
|
||||
* @param out Result of the decorrelation (out *may* alias in)
|
||||
* @param strength How much alteration of the audio to apply from 0 to 100.
|
||||
*/
|
||||
void speex_decorrelate(SpeexDecorrState *st, const spx_int16_t *in, spx_int16_t *out, int strength);
|
||||
|
||||
/** Destroy a Decorrelation state
|
||||
* @param st State to destroy
|
||||
*/
|
||||
void speex_decorrelate_destroy(SpeexDecorrState *st);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/** @}*/
|
||||
#endif
|
|
@ -0,0 +1,94 @@
|
|||
/* Copyright (C) 2002 Jean-Marc Valin */
|
||||
/**
|
||||
@file speex_header.h
|
||||
@brief Describes the Speex header
|
||||
*/
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of the Xiph.org Foundation nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SPEEX_HEADER_H
|
||||
#define SPEEX_HEADER_H
|
||||
/** @defgroup SpeexHeader SpeexHeader: Makes it easy to write/parse an Ogg/Speex header
|
||||
* This is the Speex header for the Ogg encapsulation. You don't need that if you just use RTP.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "speex/speex_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct SpeexMode;
|
||||
|
||||
/** Length of the Speex header identifier */
|
||||
#define SPEEX_HEADER_STRING_LENGTH 8
|
||||
|
||||
/** Maximum number of characters for encoding the Speex version number in the header */
|
||||
#define SPEEX_HEADER_VERSION_LENGTH 20
|
||||
|
||||
/** Speex header info for file-based formats */
|
||||
typedef struct SpeexHeader {
|
||||
char speex_string[SPEEX_HEADER_STRING_LENGTH]; /**< Identifies a Speex bit-stream, always set to "Speex " */
|
||||
char speex_version[SPEEX_HEADER_VERSION_LENGTH]; /**< Speex version */
|
||||
spx_int32_t speex_version_id; /**< Version for Speex (for checking compatibility) */
|
||||
spx_int32_t header_size; /**< Total size of the header ( sizeof(SpeexHeader) ) */
|
||||
spx_int32_t rate; /**< Sampling rate used */
|
||||
spx_int32_t mode; /**< Mode used (0 for narrowband, 1 for wideband) */
|
||||
spx_int32_t mode_bitstream_version; /**< Version ID of the bit-stream */
|
||||
spx_int32_t nb_channels; /**< Number of channels encoded */
|
||||
spx_int32_t bitrate; /**< Bit-rate used */
|
||||
spx_int32_t frame_size; /**< Size of frames */
|
||||
spx_int32_t vbr; /**< 1 for a VBR encoding, 0 otherwise */
|
||||
spx_int32_t frames_per_packet; /**< Number of frames stored per Ogg packet */
|
||||
spx_int32_t extra_headers; /**< Number of additional headers after the comments */
|
||||
spx_int32_t reserved1; /**< Reserved for future use, must be zero */
|
||||
spx_int32_t reserved2; /**< Reserved for future use, must be zero */
|
||||
} SpeexHeader;
|
||||
|
||||
/** Initializes a SpeexHeader using basic information */
|
||||
void speex_init_header(SpeexHeader *header, int rate, int nb_channels, const struct SpeexMode *m);
|
||||
|
||||
/** Creates the header packet from the header itself (mostly involves endianness conversion) */
|
||||
char *speex_header_to_packet(SpeexHeader *header, int *size);
|
||||
|
||||
/** Creates a SpeexHeader from a packet */
|
||||
SpeexHeader *speex_packet_to_header(char *packet, int size);
|
||||
|
||||
/** Frees the memory allocated by either speex_header_to_packet() or speex_packet_to_header() */
|
||||
void speex_header_free(void *ptr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
#endif
|
|
@ -0,0 +1,197 @@
|
|||
/* Copyright (C) 2002 Jean-Marc Valin */
|
||||
/**
|
||||
@file speex_jitter.h
|
||||
@brief Adaptive jitter buffer for Speex
|
||||
*/
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of the Xiph.org Foundation nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef SPEEX_JITTER_H
|
||||
#define SPEEX_JITTER_H
|
||||
/** @defgroup JitterBuffer JitterBuffer: Adaptive jitter buffer
|
||||
* This is the jitter buffer that reorders UDP/RTP packets and adjusts the buffer size
|
||||
* to maintain good quality and low latency.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "speex/speex_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Generic adaptive jitter buffer state */
|
||||
struct JitterBuffer_;
|
||||
|
||||
/** Generic adaptive jitter buffer state */
|
||||
typedef struct JitterBuffer_ JitterBuffer;
|
||||
|
||||
/** Definition of an incoming packet */
|
||||
typedef struct _JitterBufferPacket JitterBufferPacket;
|
||||
|
||||
/** Definition of an incoming packet */
|
||||
struct _JitterBufferPacket {
|
||||
char *data; /**< Data bytes contained in the packet */
|
||||
spx_uint32_t len; /**< Length of the packet in bytes */
|
||||
spx_uint32_t timestamp; /**< Timestamp for the packet */
|
||||
spx_uint32_t span; /**< Time covered by the packet (same units as timestamp) */
|
||||
spx_uint16_t sequence; /**< RTP Sequence number if available (0 otherwise) */
|
||||
spx_uint32_t user_data; /**< Put whatever data you like here (it's ignored by the jitter buffer) */
|
||||
};
|
||||
|
||||
/** Packet has been retrieved */
|
||||
#define JITTER_BUFFER_OK 0
|
||||
/** Packet is lost or is late */
|
||||
#define JITTER_BUFFER_MISSING 1
|
||||
/** A "fake" packet is meant to be inserted here to increase buffering */
|
||||
#define JITTER_BUFFER_INSERTION 2
|
||||
/** There was an error in the jitter buffer */
|
||||
#define JITTER_BUFFER_INTERNAL_ERROR -1
|
||||
/** Invalid argument */
|
||||
#define JITTER_BUFFER_BAD_ARGUMENT -2
|
||||
|
||||
|
||||
/** Set minimum amount of extra buffering required (margin) */
|
||||
#define JITTER_BUFFER_SET_MARGIN 0
|
||||
/** Get minimum amount of extra buffering required (margin) */
|
||||
#define JITTER_BUFFER_GET_MARGIN 1
|
||||
/* JITTER_BUFFER_SET_AVAILABLE_COUNT wouldn't make sense */
|
||||
|
||||
/** Get the amount of available packets currently buffered */
|
||||
#define JITTER_BUFFER_GET_AVAILABLE_COUNT 3
|
||||
/** Included because of an early misspelling (will remove in next release) */
|
||||
#define JITTER_BUFFER_GET_AVALIABLE_COUNT 3
|
||||
|
||||
/** Assign a function to destroy unused packet. When setting that, the jitter
|
||||
buffer no longer copies packet data. */
|
||||
#define JITTER_BUFFER_SET_DESTROY_CALLBACK 4
|
||||
/** */
|
||||
#define JITTER_BUFFER_GET_DESTROY_CALLBACK 5
|
||||
|
||||
/** Tell the jitter buffer to only adjust the delay in multiples of the step parameter provided */
|
||||
#define JITTER_BUFFER_SET_DELAY_STEP 6
|
||||
/** */
|
||||
#define JITTER_BUFFER_GET_DELAY_STEP 7
|
||||
|
||||
/** Tell the jitter buffer to only do concealment in multiples of the size parameter provided */
|
||||
#define JITTER_BUFFER_SET_CONCEALMENT_SIZE 8
|
||||
#define JITTER_BUFFER_GET_CONCEALMENT_SIZE 9
|
||||
|
||||
/** Absolute max amount of loss that can be tolerated regardless of the delay. Typical loss
|
||||
should be half of that or less. */
|
||||
#define JITTER_BUFFER_SET_MAX_LATE_RATE 10
|
||||
#define JITTER_BUFFER_GET_MAX_LATE_RATE 11
|
||||
|
||||
/** Equivalent cost of one percent late packet in timestamp units */
|
||||
#define JITTER_BUFFER_SET_LATE_COST 12
|
||||
#define JITTER_BUFFER_GET_LATE_COST 13
|
||||
|
||||
|
||||
/** Initialises jitter buffer
|
||||
*
|
||||
* @param step_size Starting value for the size of concleanment packets and delay
|
||||
adjustment steps. Can be changed at any time using JITTER_BUFFER_SET_DELAY_STEP
|
||||
and JITTER_BUFFER_GET_CONCEALMENT_SIZE.
|
||||
* @return Newly created jitter buffer state
|
||||
*/
|
||||
JitterBuffer *jitter_buffer_init(int step_size);
|
||||
|
||||
/** Restores jitter buffer to its original state
|
||||
*
|
||||
* @param jitter Jitter buffer state
|
||||
*/
|
||||
void jitter_buffer_reset(JitterBuffer *jitter);
|
||||
|
||||
/** Destroys jitter buffer
|
||||
*
|
||||
* @param jitter Jitter buffer state
|
||||
*/
|
||||
void jitter_buffer_destroy(JitterBuffer *jitter);
|
||||
|
||||
/** Put one packet into the jitter buffer
|
||||
*
|
||||
* @param jitter Jitter buffer state
|
||||
* @param packet Incoming packet
|
||||
*/
|
||||
void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet);
|
||||
|
||||
/** Get one packet from the jitter buffer
|
||||
*
|
||||
* @param jitter Jitter buffer state
|
||||
* @param packet Returned packet
|
||||
* @param desired_span Number of samples (or units) we wish to get from the buffer (no guarantee)
|
||||
* @param current_timestamp Timestamp for the returned packet
|
||||
*/
|
||||
int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t desired_span, spx_int32_t *start_offset);
|
||||
|
||||
/** Used right after jitter_buffer_get() to obtain another packet that would have the same timestamp.
|
||||
* This is mainly useful for media where a single "frame" can be split into several packets.
|
||||
*
|
||||
* @param jitter Jitter buffer state
|
||||
* @param packet Returned packet
|
||||
*/
|
||||
int jitter_buffer_get_another(JitterBuffer *jitter, JitterBufferPacket *packet);
|
||||
|
||||
/** Get pointer timestamp of jitter buffer
|
||||
*
|
||||
* @param jitter Jitter buffer state
|
||||
*/
|
||||
int jitter_buffer_get_pointer_timestamp(JitterBuffer *jitter);
|
||||
|
||||
/** Advance by one tick
|
||||
*
|
||||
* @param jitter Jitter buffer state
|
||||
*/
|
||||
void jitter_buffer_tick(JitterBuffer *jitter);
|
||||
|
||||
/** Telling the jitter buffer about the remaining data in the application buffer
|
||||
* @param jitter Jitter buffer state
|
||||
* @param rem Amount of data buffered by the application (timestamp units)
|
||||
*/
|
||||
void jitter_buffer_remaining_span(JitterBuffer *jitter, spx_uint32_t rem);
|
||||
|
||||
/** Used like the ioctl function to control the jitter buffer parameters
|
||||
*
|
||||
* @param jitter Jitter buffer state
|
||||
* @param request ioctl-type request (one of the JITTER_BUFFER_* macros)
|
||||
* @param ptr Data exchanged to-from function
|
||||
* @return 0 if no error, -1 if request in unknown
|
||||
*/
|
||||
int jitter_buffer_ctl(JitterBuffer *jitter, int request, void *ptr);
|
||||
|
||||
int jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t *start_offset);
|
||||
|
||||
/* @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,219 @@
|
|||
/* Copyright (C) 2003 Epic Games
|
||||
Written by Jean-Marc Valin */
|
||||
/**
|
||||
* @file speex_preprocess.h
|
||||
* @brief Speex preprocessor. The preprocess can do noise suppression,
|
||||
* residual echo suppression (after using the echo canceller), automatic
|
||||
* gain control (AGC) and voice activity detection (VAD).
|
||||
*/
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SPEEX_PREPROCESS_H
|
||||
#define SPEEX_PREPROCESS_H
|
||||
/** @defgroup SpeexPreprocessState SpeexPreprocessState: The Speex preprocessor
|
||||
* This is the Speex preprocessor. The preprocess can do noise suppression,
|
||||
* residual echo suppression (after using the echo canceller), automatic
|
||||
* gain control (AGC) and voice activity detection (VAD).
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "speex/speex_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** State of the preprocessor (one per channel). Should never be accessed directly. */
|
||||
struct SpeexPreprocessState_;
|
||||
|
||||
/** State of the preprocessor (one per channel). Should never be accessed directly. */
|
||||
typedef struct SpeexPreprocessState_ SpeexPreprocessState;
|
||||
|
||||
|
||||
/** Creates a new preprocessing state. You MUST create one state per channel processed.
|
||||
* @param frame_size Number of samples to process at one time (should correspond to 10-20 ms). Must be
|
||||
* the same value as that used for the echo canceller for residual echo cancellation to work.
|
||||
* @param sampling_rate Sampling rate used for the input.
|
||||
* @return Newly created preprocessor state
|
||||
*/
|
||||
SpeexPreprocessState *speex_preprocess_state_init(int frame_size, int sampling_rate);
|
||||
|
||||
/** Destroys a preprocessor state
|
||||
* @param st Preprocessor state to destroy
|
||||
*/
|
||||
void speex_preprocess_state_destroy(SpeexPreprocessState *st);
|
||||
|
||||
/** Preprocess a frame
|
||||
* @param st Preprocessor state
|
||||
* @param x Audio sample vector (in and out). Must be same size as specified in speex_preprocess_state_init().
|
||||
* @return Bool value for voice activity (1 for speech, 0 for noise/silence), ONLY if VAD turned on.
|
||||
*/
|
||||
int speex_preprocess_run(SpeexPreprocessState *st, spx_int16_t *x);
|
||||
|
||||
/** Preprocess a frame (deprecated, use speex_preprocess_run() instead)*/
|
||||
int speex_preprocess(SpeexPreprocessState *st, spx_int16_t *x, spx_int32_t *echo);
|
||||
|
||||
/** Update preprocessor state, but do not compute the output
|
||||
* @param st Preprocessor state
|
||||
* @param x Audio sample vector (in only). Must be same size as specified in speex_preprocess_state_init().
|
||||
*/
|
||||
void speex_preprocess_estimate_update(SpeexPreprocessState *st, spx_int16_t *x);
|
||||
|
||||
/** Used like the ioctl function to control the preprocessor parameters
|
||||
* @param st Preprocessor state
|
||||
* @param request ioctl-type request (one of the SPEEX_PREPROCESS_* macros)
|
||||
* @param ptr Data exchanged to-from function
|
||||
* @return 0 if no error, -1 if request in unknown
|
||||
*/
|
||||
int speex_preprocess_ctl(SpeexPreprocessState *st, int request, void *ptr);
|
||||
|
||||
|
||||
|
||||
/** Set preprocessor denoiser state */
|
||||
#define SPEEX_PREPROCESS_SET_DENOISE 0
|
||||
/** Get preprocessor denoiser state */
|
||||
#define SPEEX_PREPROCESS_GET_DENOISE 1
|
||||
|
||||
/** Set preprocessor Automatic Gain Control state */
|
||||
#define SPEEX_PREPROCESS_SET_AGC 2
|
||||
/** Get preprocessor Automatic Gain Control state */
|
||||
#define SPEEX_PREPROCESS_GET_AGC 3
|
||||
|
||||
/** Set preprocessor Voice Activity Detection state */
|
||||
#define SPEEX_PREPROCESS_SET_VAD 4
|
||||
/** Get preprocessor Voice Activity Detection state */
|
||||
#define SPEEX_PREPROCESS_GET_VAD 5
|
||||
|
||||
/** Set preprocessor Automatic Gain Control level (float) */
|
||||
#define SPEEX_PREPROCESS_SET_AGC_LEVEL 6
|
||||
/** Get preprocessor Automatic Gain Control level (float) */
|
||||
#define SPEEX_PREPROCESS_GET_AGC_LEVEL 7
|
||||
|
||||
/** Set preprocessor dereverb state */
|
||||
#define SPEEX_PREPROCESS_SET_DEREVERB 8
|
||||
/** Get preprocessor dereverb state */
|
||||
#define SPEEX_PREPROCESS_GET_DEREVERB 9
|
||||
|
||||
/** Set preprocessor dereverb level */
|
||||
#define SPEEX_PREPROCESS_SET_DEREVERB_LEVEL 10
|
||||
/** Get preprocessor dereverb level */
|
||||
#define SPEEX_PREPROCESS_GET_DEREVERB_LEVEL 11
|
||||
|
||||
/** Set preprocessor dereverb decay */
|
||||
#define SPEEX_PREPROCESS_SET_DEREVERB_DECAY 12
|
||||
/** Get preprocessor dereverb decay */
|
||||
#define SPEEX_PREPROCESS_GET_DEREVERB_DECAY 13
|
||||
|
||||
/** Set probability required for the VAD to go from silence to voice */
|
||||
#define SPEEX_PREPROCESS_SET_PROB_START 14
|
||||
/** Get probability required for the VAD to go from silence to voice */
|
||||
#define SPEEX_PREPROCESS_GET_PROB_START 15
|
||||
|
||||
/** Set probability required for the VAD to stay in the voice state (integer percent) */
|
||||
#define SPEEX_PREPROCESS_SET_PROB_CONTINUE 16
|
||||
/** Get probability required for the VAD to stay in the voice state (integer percent) */
|
||||
#define SPEEX_PREPROCESS_GET_PROB_CONTINUE 17
|
||||
|
||||
/** Set maximum attenuation of the noise in dB (negative number) */
|
||||
#define SPEEX_PREPROCESS_SET_NOISE_SUPPRESS 18
|
||||
/** Get maximum attenuation of the noise in dB (negative number) */
|
||||
#define SPEEX_PREPROCESS_GET_NOISE_SUPPRESS 19
|
||||
|
||||
/** Set maximum attenuation of the residual echo in dB (negative number) */
|
||||
#define SPEEX_PREPROCESS_SET_ECHO_SUPPRESS 20
|
||||
/** Get maximum attenuation of the residual echo in dB (negative number) */
|
||||
#define SPEEX_PREPROCESS_GET_ECHO_SUPPRESS 21
|
||||
|
||||
/** Set maximum attenuation of the residual echo in dB when near end is active (negative number) */
|
||||
#define SPEEX_PREPROCESS_SET_ECHO_SUPPRESS_ACTIVE 22
|
||||
/** Get maximum attenuation of the residual echo in dB when near end is active (negative number) */
|
||||
#define SPEEX_PREPROCESS_GET_ECHO_SUPPRESS_ACTIVE 23
|
||||
|
||||
/** Set the corresponding echo canceller state so that residual echo suppression can be performed (NULL for no residual echo suppression) */
|
||||
#define SPEEX_PREPROCESS_SET_ECHO_STATE 24
|
||||
/** Get the corresponding echo canceller state */
|
||||
#define SPEEX_PREPROCESS_GET_ECHO_STATE 25
|
||||
|
||||
/** Set maximal gain increase in dB/second (int32) */
|
||||
#define SPEEX_PREPROCESS_SET_AGC_INCREMENT 26
|
||||
|
||||
/** Get maximal gain increase in dB/second (int32) */
|
||||
#define SPEEX_PREPROCESS_GET_AGC_INCREMENT 27
|
||||
|
||||
/** Set maximal gain decrease in dB/second (int32) */
|
||||
#define SPEEX_PREPROCESS_SET_AGC_DECREMENT 28
|
||||
|
||||
/** Get maximal gain decrease in dB/second (int32) */
|
||||
#define SPEEX_PREPROCESS_GET_AGC_DECREMENT 29
|
||||
|
||||
/** Set maximal gain in dB (int32) */
|
||||
#define SPEEX_PREPROCESS_SET_AGC_MAX_GAIN 30
|
||||
|
||||
/** Get maximal gain in dB (int32) */
|
||||
#define SPEEX_PREPROCESS_GET_AGC_MAX_GAIN 31
|
||||
|
||||
/* Can't set loudness */
|
||||
/** Get loudness */
|
||||
#define SPEEX_PREPROCESS_GET_AGC_LOUDNESS 33
|
||||
|
||||
/* Can't set gain */
|
||||
/** Get current gain (int32 percent) */
|
||||
#define SPEEX_PREPROCESS_GET_AGC_GAIN 35
|
||||
|
||||
/* Can't set spectrum size */
|
||||
/** Get spectrum size for power spectrum (int32) */
|
||||
#define SPEEX_PREPROCESS_GET_PSD_SIZE 37
|
||||
|
||||
/* Can't set power spectrum */
|
||||
/** Get power spectrum (int32[] of squared values) */
|
||||
#define SPEEX_PREPROCESS_GET_PSD 39
|
||||
|
||||
/* Can't set noise size */
|
||||
/** Get spectrum size for noise estimate (int32) */
|
||||
#define SPEEX_PREPROCESS_GET_NOISE_PSD_SIZE 41
|
||||
|
||||
/* Can't set noise estimate */
|
||||
/** Get noise estimate (int32[] of squared values) */
|
||||
#define SPEEX_PREPROCESS_GET_NOISE_PSD 43
|
||||
|
||||
/* Can't set speech probability */
|
||||
/** Get speech probability in last frame (int32). */
|
||||
#define SPEEX_PREPROCESS_GET_PROB 45
|
||||
|
||||
/** Set preprocessor Automatic Gain Control level (int32) */
|
||||
#define SPEEX_PREPROCESS_SET_AGC_TARGET 46
|
||||
/** Get preprocessor Automatic Gain Control level (int32) */
|
||||
#define SPEEX_PREPROCESS_GET_AGC_TARGET 47
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @}*/
|
||||
#endif
|
|
@ -0,0 +1,340 @@
|
|||
/* Copyright (C) 2007 Jean-Marc Valin
|
||||
|
||||
File: speex_resampler.h
|
||||
Resampling code
|
||||
|
||||
The design goals of this code are:
|
||||
- Very fast algorithm
|
||||
- Low memory requirement
|
||||
- Good *perceptual* quality (and not best SNR)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SPEEX_RESAMPLER_H
|
||||
#define SPEEX_RESAMPLER_H
|
||||
|
||||
#ifdef OUTSIDE_SPEEX
|
||||
|
||||
/********* WARNING: MENTAL SANITY ENDS HERE *************/
|
||||
|
||||
/* If the resampler is defined outside of Speex, we change the symbol names so that
|
||||
there won't be any clash if linking with Speex later on. */
|
||||
|
||||
/* #define RANDOM_PREFIX your software name here */
|
||||
#ifndef RANDOM_PREFIX
|
||||
#error "Please define RANDOM_PREFIX (above) to something specific to your project to prevent symbol name clashes"
|
||||
#endif
|
||||
|
||||
#define CAT_PREFIX2(a,b) a ## b
|
||||
#define CAT_PREFIX(a,b) CAT_PREFIX2(a, b)
|
||||
|
||||
#define speex_resampler_init CAT_PREFIX(RANDOM_PREFIX,_resampler_init)
|
||||
#define speex_resampler_init_frac CAT_PREFIX(RANDOM_PREFIX,_resampler_init_frac)
|
||||
#define speex_resampler_destroy CAT_PREFIX(RANDOM_PREFIX,_resampler_destroy)
|
||||
#define speex_resampler_process_float CAT_PREFIX(RANDOM_PREFIX,_resampler_process_float)
|
||||
#define speex_resampler_process_int CAT_PREFIX(RANDOM_PREFIX,_resampler_process_int)
|
||||
#define speex_resampler_process_interleaved_float CAT_PREFIX(RANDOM_PREFIX,_resampler_process_interleaved_float)
|
||||
#define speex_resampler_process_interleaved_int CAT_PREFIX(RANDOM_PREFIX,_resampler_process_interleaved_int)
|
||||
#define speex_resampler_set_rate CAT_PREFIX(RANDOM_PREFIX,_resampler_set_rate)
|
||||
#define speex_resampler_get_rate CAT_PREFIX(RANDOM_PREFIX,_resampler_get_rate)
|
||||
#define speex_resampler_set_rate_frac CAT_PREFIX(RANDOM_PREFIX,_resampler_set_rate_frac)
|
||||
#define speex_resampler_get_ratio CAT_PREFIX(RANDOM_PREFIX,_resampler_get_ratio)
|
||||
#define speex_resampler_set_quality CAT_PREFIX(RANDOM_PREFIX,_resampler_set_quality)
|
||||
#define speex_resampler_get_quality CAT_PREFIX(RANDOM_PREFIX,_resampler_get_quality)
|
||||
#define speex_resampler_set_input_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_set_input_stride)
|
||||
#define speex_resampler_get_input_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_get_input_stride)
|
||||
#define speex_resampler_set_output_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_set_output_stride)
|
||||
#define speex_resampler_get_output_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_get_output_stride)
|
||||
#define speex_resampler_get_input_latency CAT_PREFIX(RANDOM_PREFIX,_resampler_get_input_latency)
|
||||
#define speex_resampler_get_output_latency CAT_PREFIX(RANDOM_PREFIX,_resampler_get_output_latency)
|
||||
#define speex_resampler_skip_zeros CAT_PREFIX(RANDOM_PREFIX,_resampler_skip_zeros)
|
||||
#define speex_resampler_reset_mem CAT_PREFIX(RANDOM_PREFIX,_resampler_reset_mem)
|
||||
#define speex_resampler_strerror CAT_PREFIX(RANDOM_PREFIX,_resampler_strerror)
|
||||
|
||||
#define spx_int16_t short
|
||||
#define spx_int32_t int
|
||||
#define spx_uint16_t unsigned short
|
||||
#define spx_uint32_t unsigned int
|
||||
|
||||
#else /* OUTSIDE_SPEEX */
|
||||
|
||||
#include "speex/speex_types.h"
|
||||
|
||||
#endif /* OUTSIDE_SPEEX */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define SPEEX_RESAMPLER_QUALITY_MAX 10
|
||||
#define SPEEX_RESAMPLER_QUALITY_MIN 0
|
||||
#define SPEEX_RESAMPLER_QUALITY_DEFAULT 4
|
||||
#define SPEEX_RESAMPLER_QUALITY_VOIP 3
|
||||
#define SPEEX_RESAMPLER_QUALITY_DESKTOP 5
|
||||
|
||||
enum {
|
||||
RESAMPLER_ERR_SUCCESS = 0,
|
||||
RESAMPLER_ERR_ALLOC_FAILED = 1,
|
||||
RESAMPLER_ERR_BAD_STATE = 2,
|
||||
RESAMPLER_ERR_INVALID_ARG = 3,
|
||||
RESAMPLER_ERR_PTR_OVERLAP = 4,
|
||||
|
||||
RESAMPLER_ERR_MAX_ERROR
|
||||
};
|
||||
|
||||
struct SpeexResamplerState_;
|
||||
typedef struct SpeexResamplerState_ SpeexResamplerState;
|
||||
|
||||
/** Create a new resampler with integer input and output rates.
|
||||
* @param nb_channels Number of channels to be processed
|
||||
* @param in_rate Input sampling rate (integer number of Hz).
|
||||
* @param out_rate Output sampling rate (integer number of Hz).
|
||||
* @param quality Resampling quality between 0 and 10, where 0 has poor quality
|
||||
* and 10 has very high quality.
|
||||
* @return Newly created resampler state
|
||||
* @retval NULL Error: not enough memory
|
||||
*/
|
||||
SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels,
|
||||
spx_uint32_t in_rate,
|
||||
spx_uint32_t out_rate,
|
||||
int quality,
|
||||
int *err);
|
||||
|
||||
/** Create a new resampler with fractional input/output rates. The sampling
|
||||
* rate ratio is an arbitrary rational number with both the numerator and
|
||||
* denominator being 32-bit integers.
|
||||
* @param nb_channels Number of channels to be processed
|
||||
* @param ratio_num Numerator of the sampling rate ratio
|
||||
* @param ratio_den Denominator of the sampling rate ratio
|
||||
* @param in_rate Input sampling rate rounded to the nearest integer (in Hz).
|
||||
* @param out_rate Output sampling rate rounded to the nearest integer (in Hz).
|
||||
* @param quality Resampling quality between 0 and 10, where 0 has poor quality
|
||||
* and 10 has very high quality.
|
||||
* @return Newly created resampler state
|
||||
* @retval NULL Error: not enough memory
|
||||
*/
|
||||
SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels,
|
||||
spx_uint32_t ratio_num,
|
||||
spx_uint32_t ratio_den,
|
||||
spx_uint32_t in_rate,
|
||||
spx_uint32_t out_rate,
|
||||
int quality,
|
||||
int *err);
|
||||
|
||||
/** Destroy a resampler state.
|
||||
* @param st Resampler state
|
||||
*/
|
||||
void speex_resampler_destroy(SpeexResamplerState *st);
|
||||
|
||||
/** Resample a float array. The input and output buffers must *not* overlap.
|
||||
* @param st Resampler state
|
||||
* @param channel_index Index of the channel to process for the multi-channel
|
||||
* base (0 otherwise)
|
||||
* @param in Input buffer
|
||||
* @param in_len Number of input samples in the input buffer. Returns the
|
||||
* number of samples processed
|
||||
* @param out Output buffer
|
||||
* @param out_len Size of the output buffer. Returns the number of samples written
|
||||
*/
|
||||
int speex_resampler_process_float(SpeexResamplerState *st,
|
||||
spx_uint32_t channel_index,
|
||||
const float *in,
|
||||
spx_uint32_t *in_len,
|
||||
float *out,
|
||||
spx_uint32_t *out_len);
|
||||
|
||||
/** Resample an int array. The input and output buffers must *not* overlap.
|
||||
* @param st Resampler state
|
||||
* @param channel_index Index of the channel to process for the multi-channel
|
||||
* base (0 otherwise)
|
||||
* @param in Input buffer
|
||||
* @param in_len Number of input samples in the input buffer. Returns the number
|
||||
* of samples processed
|
||||
* @param out Output buffer
|
||||
* @param out_len Size of the output buffer. Returns the number of samples written
|
||||
*/
|
||||
int speex_resampler_process_int(SpeexResamplerState *st,
|
||||
spx_uint32_t channel_index,
|
||||
const spx_int16_t *in,
|
||||
spx_uint32_t *in_len,
|
||||
spx_int16_t *out,
|
||||
spx_uint32_t *out_len);
|
||||
|
||||
/** Resample an interleaved float array. The input and output buffers must *not* overlap.
|
||||
* @param st Resampler state
|
||||
* @param in Input buffer
|
||||
* @param in_len Number of input samples in the input buffer. Returns the number
|
||||
* of samples processed. This is all per-channel.
|
||||
* @param out Output buffer
|
||||
* @param out_len Size of the output buffer. Returns the number of samples written.
|
||||
* This is all per-channel.
|
||||
*/
|
||||
int speex_resampler_process_interleaved_float(SpeexResamplerState *st,
|
||||
const float *in,
|
||||
spx_uint32_t *in_len,
|
||||
float *out,
|
||||
spx_uint32_t *out_len);
|
||||
|
||||
/** Resample an interleaved int array. The input and output buffers must *not* overlap.
|
||||
* @param st Resampler state
|
||||
* @param in Input buffer
|
||||
* @param in_len Number of input samples in the input buffer. Returns the number
|
||||
* of samples processed. This is all per-channel.
|
||||
* @param out Output buffer
|
||||
* @param out_len Size of the output buffer. Returns the number of samples written.
|
||||
* This is all per-channel.
|
||||
*/
|
||||
int speex_resampler_process_interleaved_int(SpeexResamplerState *st,
|
||||
const spx_int16_t *in,
|
||||
spx_uint32_t *in_len,
|
||||
spx_int16_t *out,
|
||||
spx_uint32_t *out_len);
|
||||
|
||||
/** Set (change) the input/output sampling rates (integer value).
|
||||
* @param st Resampler state
|
||||
* @param in_rate Input sampling rate (integer number of Hz).
|
||||
* @param out_rate Output sampling rate (integer number of Hz).
|
||||
*/
|
||||
int speex_resampler_set_rate(SpeexResamplerState *st,
|
||||
spx_uint32_t in_rate,
|
||||
spx_uint32_t out_rate);
|
||||
|
||||
/** Get the current input/output sampling rates (integer value).
|
||||
* @param st Resampler state
|
||||
* @param in_rate Input sampling rate (integer number of Hz) copied.
|
||||
* @param out_rate Output sampling rate (integer number of Hz) copied.
|
||||
*/
|
||||
void speex_resampler_get_rate(SpeexResamplerState *st,
|
||||
spx_uint32_t *in_rate,
|
||||
spx_uint32_t *out_rate);
|
||||
|
||||
/** Set (change) the input/output sampling rates and resampling ratio
|
||||
* (fractional values in Hz supported).
|
||||
* @param st Resampler state
|
||||
* @param ratio_num Numerator of the sampling rate ratio
|
||||
* @param ratio_den Denominator of the sampling rate ratio
|
||||
* @param in_rate Input sampling rate rounded to the nearest integer (in Hz).
|
||||
* @param out_rate Output sampling rate rounded to the nearest integer (in Hz).
|
||||
*/
|
||||
int speex_resampler_set_rate_frac(SpeexResamplerState *st,
|
||||
spx_uint32_t ratio_num,
|
||||
spx_uint32_t ratio_den,
|
||||
spx_uint32_t in_rate,
|
||||
spx_uint32_t out_rate);
|
||||
|
||||
/** Get the current resampling ratio. This will be reduced to the least
|
||||
* common denominator.
|
||||
* @param st Resampler state
|
||||
* @param ratio_num Numerator of the sampling rate ratio copied
|
||||
* @param ratio_den Denominator of the sampling rate ratio copied
|
||||
*/
|
||||
void speex_resampler_get_ratio(SpeexResamplerState *st,
|
||||
spx_uint32_t *ratio_num,
|
||||
spx_uint32_t *ratio_den);
|
||||
|
||||
/** Set (change) the conversion quality.
|
||||
* @param st Resampler state
|
||||
* @param quality Resampling quality between 0 and 10, where 0 has poor
|
||||
* quality and 10 has very high quality.
|
||||
*/
|
||||
int speex_resampler_set_quality(SpeexResamplerState *st,
|
||||
int quality);
|
||||
|
||||
/** Get the conversion quality.
|
||||
* @param st Resampler state
|
||||
* @param quality Resampling quality between 0 and 10, where 0 has poor
|
||||
* quality and 10 has very high quality.
|
||||
*/
|
||||
void speex_resampler_get_quality(SpeexResamplerState *st,
|
||||
int *quality);
|
||||
|
||||
/** Set (change) the input stride.
|
||||
* @param st Resampler state
|
||||
* @param stride Input stride
|
||||
*/
|
||||
void speex_resampler_set_input_stride(SpeexResamplerState *st,
|
||||
spx_uint32_t stride);
|
||||
|
||||
/** Get the input stride.
|
||||
* @param st Resampler state
|
||||
* @param stride Input stride copied
|
||||
*/
|
||||
void speex_resampler_get_input_stride(SpeexResamplerState *st,
|
||||
spx_uint32_t *stride);
|
||||
|
||||
/** Set (change) the output stride.
|
||||
* @param st Resampler state
|
||||
* @param stride Output stride
|
||||
*/
|
||||
void speex_resampler_set_output_stride(SpeexResamplerState *st,
|
||||
spx_uint32_t stride);
|
||||
|
||||
/** Get the output stride.
|
||||
* @param st Resampler state copied
|
||||
* @param stride Output stride
|
||||
*/
|
||||
void speex_resampler_get_output_stride(SpeexResamplerState *st,
|
||||
spx_uint32_t *stride);
|
||||
|
||||
/** Get the latency in input samples introduced by the resampler.
|
||||
* @param st Resampler state
|
||||
*/
|
||||
int speex_resampler_get_input_latency(SpeexResamplerState *st);
|
||||
|
||||
/** Get the latency in output samples introduced by the resampler.
|
||||
* @param st Resampler state
|
||||
*/
|
||||
int speex_resampler_get_output_latency(SpeexResamplerState *st);
|
||||
|
||||
/** Make sure that the first samples to go out of the resamplers don't have
|
||||
* leading zeros. This is only useful before starting to use a newly created
|
||||
* resampler. It is recommended to use that when resampling an audio file, as
|
||||
* it will generate a file with the same length. For real-time processing,
|
||||
* it is probably easier not to use this call (so that the output duration
|
||||
* is the same for the first frame).
|
||||
* @param st Resampler state
|
||||
*/
|
||||
int speex_resampler_skip_zeros(SpeexResamplerState *st);
|
||||
|
||||
/** Reset a resampler so a new (unrelated) stream can be processed.
|
||||
* @param st Resampler state
|
||||
*/
|
||||
int speex_resampler_reset_mem(SpeexResamplerState *st);
|
||||
|
||||
/** Returns the English meaning for an error code
|
||||
* @param err Error code
|
||||
* @return English string
|
||||
*/
|
||||
const char *speex_resampler_strerror(int err);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,91 @@
|
|||
/* Copyright (C) 2002 Jean-Marc Valin*/
|
||||
/**
|
||||
@file speex_stereo.h
|
||||
@brief Describes the handling for intensity stereo
|
||||
*/
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of the Xiph.org Foundation nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef STEREO_H
|
||||
#define STEREO_H
|
||||
/** @defgroup SpeexStereoState SpeexStereoState: Handling Speex stereo files
|
||||
* This describes the Speex intensity stereo encoding/decoding
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "speex/speex_types.h"
|
||||
#include "speex/speex_bits.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** If you access any of these fields directly, I'll personally come and bite you */
|
||||
typedef struct SpeexStereoState {
|
||||
float balance; /**< Left/right balance info */
|
||||
float e_ratio; /**< Ratio of energies: E(left+right)/[E(left)+E(right)] */
|
||||
float smooth_left; /**< Smoothed left channel gain */
|
||||
float smooth_right; /**< Smoothed right channel gain */
|
||||
float reserved1; /**< Reserved for future use */
|
||||
float reserved2; /**< Reserved for future use */
|
||||
} SpeexStereoState;
|
||||
|
||||
/** Deprecated. Use speex_stereo_state_init() instead. */
|
||||
#define SPEEX_STEREO_STATE_INIT {1,.5,1,1,0,0}
|
||||
|
||||
/** Initialise/create a stereo stereo state */
|
||||
SpeexStereoState *speex_stereo_state_init();
|
||||
|
||||
/** Reset/re-initialise an already allocated stereo state */
|
||||
void speex_stereo_state_reset(SpeexStereoState *stereo);
|
||||
|
||||
/** Destroy a stereo stereo state */
|
||||
void speex_stereo_state_destroy(SpeexStereoState *stereo);
|
||||
|
||||
/** Transforms a stereo frame into a mono frame and stores intensity stereo info in 'bits' */
|
||||
void speex_encode_stereo(float *data, int frame_size, SpeexBits *bits);
|
||||
|
||||
/** Transforms a stereo frame into a mono frame and stores intensity stereo info in 'bits' */
|
||||
void speex_encode_stereo_int(spx_int16_t *data, int frame_size, SpeexBits *bits);
|
||||
|
||||
/** Transforms a mono frame into a stereo frame using intensity stereo info */
|
||||
void speex_decode_stereo(float *data, int frame_size, SpeexStereoState *stereo);
|
||||
|
||||
/** Transforms a mono frame into a stereo frame using intensity stereo info */
|
||||
void speex_decode_stereo_int(spx_int16_t *data, int frame_size, SpeexStereoState *stereo);
|
||||
|
||||
/** Callback handler for intensity stereo info */
|
||||
int speex_std_stereo_request_handler(SpeexBits *bits, void *state, void *data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
#endif
|
|
@ -0,0 +1,133 @@
|
|||
/* speex_types.h taken from libogg */
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: #ifdef jail to whip a few platforms into the UNIX ideal.
|
||||
last mod: $Id: os_types.h 7524 2004-08-11 04:20:36Z conrad $
|
||||
|
||||
********************************************************************/
|
||||
/**
|
||||
@file speex_types.h
|
||||
@brief Speex types
|
||||
*/
|
||||
#ifndef _SPEEX_TYPES_H
|
||||
#define _SPEEX_TYPES_H
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
# if defined(__CYGWIN__)
|
||||
# include <_G_config.h>
|
||||
typedef _G_int32_t spx_int32_t;
|
||||
typedef _G_uint32_t spx_uint32_t;
|
||||
typedef _G_int16_t spx_int16_t;
|
||||
typedef _G_uint16_t spx_uint16_t;
|
||||
# elif defined(__MINGW32__)
|
||||
typedef short spx_int16_t;
|
||||
typedef unsigned short spx_uint16_t;
|
||||
typedef int spx_int32_t;
|
||||
typedef unsigned int spx_uint32_t;
|
||||
# elif defined(__MWERKS__)
|
||||
typedef int spx_int32_t;
|
||||
typedef unsigned int spx_uint32_t;
|
||||
typedef short spx_int16_t;
|
||||
typedef unsigned short spx_uint16_t;
|
||||
# else
|
||||
/* MSVC/Borland */
|
||||
typedef __int32 spx_int32_t;
|
||||
typedef unsigned __int32 spx_uint32_t;
|
||||
typedef __int16 spx_int16_t;
|
||||
typedef unsigned __int16 spx_uint16_t;
|
||||
# endif
|
||||
|
||||
#elif defined(__MACOS__)
|
||||
|
||||
# include <sys/types.h>
|
||||
typedef SInt16 spx_int16_t;
|
||||
typedef UInt16 spx_uint16_t;
|
||||
typedef SInt32 spx_int32_t;
|
||||
typedef UInt32 spx_uint32_t;
|
||||
|
||||
#elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */
|
||||
|
||||
# include <sys/types.h>
|
||||
typedef int16_t spx_int16_t;
|
||||
typedef u_int16_t spx_uint16_t;
|
||||
typedef int32_t spx_int32_t;
|
||||
typedef u_int32_t spx_uint32_t;
|
||||
|
||||
#elif defined(__BEOS__)
|
||||
|
||||
/* Be */
|
||||
# include <inttypes.h>
|
||||
typedef int16_t spx_int16_t;
|
||||
typedef u_int16_t spx_uint16_t;
|
||||
typedef int32_t spx_int32_t;
|
||||
typedef u_int32_t spx_uint32_t;
|
||||
|
||||
#elif defined (__EMX__)
|
||||
|
||||
/* OS/2 GCC */
|
||||
typedef short spx_int16_t;
|
||||
typedef unsigned short spx_uint16_t;
|
||||
typedef int spx_int32_t;
|
||||
typedef unsigned int spx_uint32_t;
|
||||
|
||||
#elif defined (DJGPP)
|
||||
|
||||
/* DJGPP */
|
||||
typedef short spx_int16_t;
|
||||
typedef int spx_int32_t;
|
||||
typedef unsigned int spx_uint32_t;
|
||||
|
||||
#elif defined(R5900)
|
||||
|
||||
/* PS2 EE */
|
||||
typedef int spx_int32_t;
|
||||
typedef unsigned spx_uint32_t;
|
||||
typedef short spx_int16_t;
|
||||
|
||||
#elif defined(__SYMBIAN32__)
|
||||
|
||||
/* Symbian GCC */
|
||||
typedef signed short spx_int16_t;
|
||||
typedef unsigned short spx_uint16_t;
|
||||
typedef signed int spx_int32_t;
|
||||
typedef unsigned int spx_uint32_t;
|
||||
|
||||
#elif defined(CONFIG_TI_C54X) || defined (CONFIG_TI_C55X)
|
||||
|
||||
typedef short spx_int16_t;
|
||||
typedef unsigned short spx_uint16_t;
|
||||
typedef long spx_int32_t;
|
||||
typedef unsigned long spx_uint32_t;
|
||||
|
||||
#elif defined(CONFIG_TI_C6X)
|
||||
|
||||
typedef short spx_int16_t;
|
||||
typedef unsigned short spx_uint16_t;
|
||||
typedef int spx_int32_t;
|
||||
typedef unsigned int spx_uint32_t;
|
||||
|
||||
#elif ANDROID
|
||||
|
||||
typedef short spx_int16_t;
|
||||
typedef unsigned short spx_uint16_t;
|
||||
typedef int spx_int32_t;
|
||||
typedef unsigned int spx_uint32_t;
|
||||
|
||||
#else
|
||||
|
||||
# include <speex/speex_config_types.h>
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _SPEEX_TYPES_H */
|
|
@ -33,11 +33,12 @@ TDAV_BEGIN_DECLS
|
|||
|
||||
typedef void* tdav_audiounit_handle_t;
|
||||
|
||||
tdav_audiounit_handle_t* tdav_audiounit_handle_create(uint64_t session_id);
|
||||
AudioComponentInstance tdav_audiounit_handle_get_instance(tdav_audiounit_handle_t* self);
|
||||
tdav_audiounit_handle_t* tdav_audiounit_handle_create(uint64_t session_id, uint32_t ptime);
|
||||
/*inline*/ AudioComponentInstance tdav_audiounit_handle_get_instance(tdav_audiounit_handle_t* self);
|
||||
int tdav_audiounit_handle_signal_consumer_prepared(tdav_audiounit_handle_t* self);
|
||||
int tdav_audiounit_handle_signal_producer_prepared(tdav_audiounit_handle_t* self);
|
||||
int tdav_audiounit_handle_start(tdav_audiounit_handle_t* self);
|
||||
uint32_t tdav_audiounit_handle_get_frame_duration(tdav_audiounit_handle_t* self);
|
||||
int tdav_audiounit_handle_stop(tdav_audiounit_handle_t* self);
|
||||
int tdav_audiounit_handle_destroy(tdav_audiounit_handle_t** self);
|
||||
|
||||
|
|
|
@ -27,9 +27,12 @@
|
|||
#if HAVE_COREAUDIO_AUDIO_UNIT
|
||||
|
||||
#include <AudioToolbox/AudioToolbox.h>
|
||||
#include <speex/speex_buffer.h>
|
||||
#include "tinydav/audio/coreaudio/tdav_audiounit.h"
|
||||
#include "tinydav/audio/tdav_consumer_audio.h"
|
||||
|
||||
#include "tsk_mutex.h"
|
||||
|
||||
TDAV_BEGIN_DECLS
|
||||
|
||||
typedef struct tdav_consumer_audiounit_s
|
||||
|
@ -37,8 +40,18 @@ typedef struct tdav_consumer_audiounit_s
|
|||
TDAV_DECLARE_CONSUMER_AUDIO;
|
||||
|
||||
tdav_audiounit_handle_t* audioUnitHandle;
|
||||
tsk_bool_t started;
|
||||
tsk_bool_t paused;
|
||||
unsigned started:1;
|
||||
unsigned paused:1;
|
||||
|
||||
struct {
|
||||
struct {
|
||||
void* buffer;
|
||||
tsk_size_t size;
|
||||
} chunck;
|
||||
SpeexBuffer* buffer;
|
||||
tsk_size_t size;
|
||||
tsk_mutex_handle_t* mutex;
|
||||
} ring;
|
||||
}
|
||||
tdav_consumer_audiounit_t;
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#if HAVE_COREAUDIO_AUDIO_UNIT
|
||||
|
||||
#include <AudioToolbox/AudioToolbox.h>
|
||||
#include <speex/speex_buffer.h>
|
||||
#include "tinydav/audio/coreaudio/tdav_audiounit.h"
|
||||
#include "tinydav/audio/tdav_producer_audio.h"
|
||||
|
||||
|
@ -37,8 +38,17 @@ typedef struct tdav_producer_audiounit_s
|
|||
TDAV_DECLARE_PRODUCER_AUDIO;
|
||||
|
||||
tdav_audiounit_handle_t* audioUnitHandle;
|
||||
tsk_bool_t started;
|
||||
tsk_bool_t paused;
|
||||
unsigned started:1;
|
||||
unsigned paused:1;
|
||||
|
||||
struct {
|
||||
struct {
|
||||
void* buffer;
|
||||
tsk_size_t size;
|
||||
} chunck;
|
||||
SpeexBuffer* buffer;
|
||||
tsk_size_t size;
|
||||
} ring;
|
||||
}
|
||||
tdav_producer_audiounit_t;
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ typedef struct tdav_speakup_jitterBuffer_s
|
|||
jitterbuffer *jbuffer;
|
||||
uint8_t jcodec;
|
||||
uint64_t ref_timestamp;
|
||||
uint32_t framesize;
|
||||
uint32_t frame_duration;
|
||||
uint32_t rate;
|
||||
}
|
||||
tdav_speakup_jitterbuffer_t;
|
||||
|
|
|
@ -45,6 +45,7 @@ typedef struct tdav_speex_jitterBuffer_s
|
|||
|
||||
JitterBuffer* state;
|
||||
uint32_t rate;
|
||||
uint32_t frame_duration;
|
||||
}
|
||||
tdav_speex_jitterbuffer_t;
|
||||
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright (C) 2010-2011 Mamadou Diop.
|
||||
*
|
||||
* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
|
||||
*
|
||||
* This file is part of Open Source Doubango Framework.
|
||||
*
|
||||
* DOUBANGO is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* DOUBANGO is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with DOUBANGO.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TDAV_APPLE_H
|
||||
#define TDAV_APPLE_H
|
||||
|
||||
#if TDAV_UNDER_APPLE
|
||||
|
||||
#include <AudioToolbox/AudioToolbox.h>
|
||||
|
||||
#include "tsk_debug.h"
|
||||
|
||||
static int tdav_apple_init()
|
||||
{
|
||||
// initialize audio session
|
||||
OSStatus status;
|
||||
status = AudioSessionInitialize(NULL, NULL, NULL, NULL);
|
||||
if(status){
|
||||
TSK_DEBUG_ERROR("AudioSessionInitialize() failed with status code=%d", (int32_t)status);
|
||||
return -1;
|
||||
}
|
||||
|
||||
UInt32 audioCategory = kAudioSessionCategory_PlayAndRecord;
|
||||
status = AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(audioCategory), &audioCategory);
|
||||
if(status){
|
||||
TSK_DEBUG_ERROR("AudioSessionSetProperty(kAudioSessionProperty_AudioCategory) failed with status code=%d", (int32_t)status);
|
||||
return -2;
|
||||
}
|
||||
// enable audio session
|
||||
status = AudioSessionSetActive(true);
|
||||
if(status){
|
||||
TSK_DEBUG_ERROR("AudioSessionSetActive(true) failed with status code=%d", (int32_t)status);
|
||||
return -3;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tdav_apple_deinit()
|
||||
{
|
||||
// maybe other code use the session
|
||||
// OSStatus status = AudioSessionSetActive(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* TDAV_UNDER_APPLE */
|
||||
|
||||
#endif /* TDAV_APPLE_H */
|
|
@ -37,7 +37,9 @@
|
|||
|
||||
TDAV_BEGIN_DECLS
|
||||
|
||||
int tdav_win32_init();
|
||||
void tdav_win32_print_error(const char* func, HRESULT hr);
|
||||
int tdav_win32_deinit();
|
||||
|
||||
TDAV_END_DECLS
|
||||
|
||||
|
|
|
@ -27,12 +27,16 @@
|
|||
#undef _WIN32 /* Because of WINSCW */
|
||||
#endif
|
||||
|
||||
/* Windows (XP/Vista/7/CE and Windows Mobile) macro definition.
|
||||
*/
|
||||
/* Windows (XP/Vista/7/CE and Windows Mobile) macro definition. */
|
||||
#if defined(WIN32)|| defined(_WIN32) || defined(_WIN32_WCE)
|
||||
# define TDAV_UNDER_WINDOWS 1
|
||||
#endif
|
||||
|
||||
/* OS X or iOS */
|
||||
#if defined(__APPLE__)
|
||||
# define TDAV_UNDER_APPLE 1
|
||||
#endif
|
||||
|
||||
#if (TDAV_UNDER_WINDOWS || defined(__SYMBIAN32__)) && defined(TINYDAV_EXPORTS)
|
||||
# define TINYDAV_API __declspec(dllexport)
|
||||
# define TINYDAV_GEXTERN __declspec(dllexport)
|
||||
|
@ -44,8 +48,7 @@
|
|||
# define TINYDAV_GEXTERN extern
|
||||
#endif
|
||||
|
||||
/* Guards against C++ name mangling
|
||||
*/
|
||||
/* Guards against C++ name mangling */
|
||||
#ifdef __cplusplus
|
||||
# define TDAV_BEGIN_DECLS extern "C" {
|
||||
# define TDAV_END_DECLS }
|
||||
|
|
|
@ -37,6 +37,7 @@ typedef struct tdav_audiounit_instance_s
|
|||
{
|
||||
TSK_DECLARE_OBJECT;
|
||||
uint64_t session_id;
|
||||
uint32_t frame_duration;
|
||||
AudioComponentInstance audioUnit;
|
||||
struct{
|
||||
unsigned consumer:1;
|
||||
|
@ -84,7 +85,7 @@ static int _tdav_audiounit_handle_signal_xxx_prepared(tdav_audiounit_handle_t* s
|
|||
return 0;
|
||||
}
|
||||
|
||||
tdav_audiounit_handle_t* tdav_audiounit_handle_create(uint64_t session_id)
|
||||
tdav_audiounit_handle_t* tdav_audiounit_handle_create(uint64_t session_id, uint32_t ptime)
|
||||
{
|
||||
tdav_audiounit_instance_t* inst = tsk_null;
|
||||
const tsk_list_item_t* item;
|
||||
|
@ -96,11 +97,14 @@ tdav_audiounit_handle_t* tdav_audiounit_handle_create(uint64_t session_id)
|
|||
audioDescription.componentManufacturer = kAudioUnitManufacturer_Apple;
|
||||
audioDescription.componentFlags = 0;
|
||||
audioDescription.componentFlagsMask = 0;
|
||||
__audioSystem = AudioComponentFindNext(NULL, &audioDescription);
|
||||
}
|
||||
if(!__audioSystem){
|
||||
TSK_DEBUG_ERROR("Failed to find new audio component");
|
||||
goto done;
|
||||
if((__audioSystem = AudioComponentFindNext(NULL, &audioDescription))){
|
||||
// leave blank
|
||||
}
|
||||
else {
|
||||
TSK_DEBUG_ERROR("Failed to find new audio component");
|
||||
goto done;
|
||||
}
|
||||
|
||||
}
|
||||
// create list used to hold instances
|
||||
if(!__audioUnitInstances && !(__audioUnitInstances = tsk_list_create())){
|
||||
|
@ -123,11 +127,44 @@ tdav_audiounit_handle_t* tdav_audiounit_handle_create(uint64_t session_id)
|
|||
if((inst = tsk_object_new(tdav_audiounit_instance_def_t))){
|
||||
OSStatus status;
|
||||
tdav_audiounit_instance_t* _inst;
|
||||
// set preferred buffer size
|
||||
Float32 preferredBufferSize = (Float32)ptime / 1000.f; // in seconds
|
||||
status = AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration, sizeof(preferredBufferSize), &preferredBufferSize);
|
||||
if(status){
|
||||
TSK_DEBUG_ERROR("AudioUnitSetProperty(kAudioOutputUnitProperty_SetInputCallback) failed with status=%d", (int32_t)status);
|
||||
TSK_OBJECT_SAFE_FREE(inst);
|
||||
goto done;
|
||||
}
|
||||
UInt32 size = sizeof(preferredBufferSize);
|
||||
status = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareIOBufferDuration, &size, &preferredBufferSize);
|
||||
if(!status){
|
||||
inst->frame_duration = (preferredBufferSize * 1000);
|
||||
TSK_DEBUG_INFO("Frame duration=%d", inst->frame_duration);
|
||||
}
|
||||
else {
|
||||
TSK_DEBUG_ERROR("AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareIOBufferDuration, %f) failed", preferredBufferSize);
|
||||
}
|
||||
|
||||
// create new instance
|
||||
if((status= AudioComponentInstanceNew(__audioSystem, &inst->audioUnit))){
|
||||
TSK_DEBUG_ERROR("AudioComponentInstanceNew() failed with status=%d", (int32_t)status);
|
||||
TSK_OBJECT_SAFE_FREE(inst);
|
||||
goto done;
|
||||
}
|
||||
// enable all even if we know that it's already done by default
|
||||
static UInt32 kOne = 1;
|
||||
static UInt32 kZero = 0;
|
||||
// static UInt32 kVoiceQuality = 127;
|
||||
#define kInputBus 1
|
||||
status = AudioUnitSetProperty(inst->audioUnit, kAUVoiceIOProperty_BypassVoiceProcessing,
|
||||
kAudioUnitScope_Global, kInputBus, &kZero, sizeof(kZero));
|
||||
status = AudioUnitSetProperty(inst->audioUnit, kAUVoiceIOProperty_VoiceProcessingEnableAGC,
|
||||
kAudioUnitScope_Global, kInputBus, &kOne, sizeof(kOne));
|
||||
status = AudioUnitSetProperty(inst->audioUnit, kAUVoiceIOProperty_DuckNonVoiceAudio,
|
||||
kAudioUnitScope_Global, kInputBus, &kOne, sizeof(kOne));
|
||||
// status = AudioUnitSetProperty(inst->audioUnit, kAUVoiceIOProperty_VoiceProcessingQuality,
|
||||
// kAudioUnitScope_Global, kInputBus, &kVoiceQuality, sizeof(kVoiceQuality));
|
||||
|
||||
_inst = inst, _inst->session_id = session_id;
|
||||
tsk_list_push_back_data(__audioUnitInstances, (void**)&_inst);
|
||||
}
|
||||
|
@ -175,6 +212,14 @@ int tdav_audiounit_handle_start(tdav_audiounit_handle_t* self)
|
|||
return status ? -2 : 0;
|
||||
}
|
||||
|
||||
uint32_t tdav_audiounit_handle_get_frame_duration(tdav_audiounit_handle_t* self)
|
||||
{
|
||||
if(self){
|
||||
return ((tdav_audiounit_instance_t*)self)->frame_duration;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tdav_audiounit_handle_stop(tdav_audiounit_handle_t* self)
|
||||
{
|
||||
tdav_audiounit_instance_t* inst = (tdav_audiounit_instance_t*)self;
|
||||
|
|
|
@ -40,26 +40,21 @@
|
|||
#include "tsk_debug.h"
|
||||
|
||||
static void __handle_output_buffer(void *userdata, AudioQueueRef queue, AudioQueueBufferRef buffer) {
|
||||
OSStatus ret;
|
||||
void *data;
|
||||
tsk_size_t out_size = 0;
|
||||
tdav_consumer_audioqueue_t* consumer = (tdav_consumer_audioqueue_t*)userdata;
|
||||
|
||||
if (!consumer->started) {
|
||||
return;
|
||||
}
|
||||
|
||||
if((data = tdav_consumer_audio_get(TDAV_CONSUMER_AUDIO(consumer), &out_size))){
|
||||
// If we can get audio to play, then copy in the buffer
|
||||
memcpy(buffer->mAudioData, data, TSK_MIN(consumer->buffer_size, out_size));
|
||||
TSK_FREE(data);
|
||||
} else{
|
||||
// Put silence if there is no audio to play
|
||||
memset(buffer->mAudioData, 0, consumer->buffer_size);
|
||||
if(!tdav_consumer_audio_get(TDAV_CONSUMER_AUDIO(consumer), buffer->mAudioData, consumer->buffer_size)){
|
||||
// Put silence
|
||||
memset(buffer->mAudioData, 0, consumer->buffer_size);
|
||||
}
|
||||
|
||||
// Re-enqueue the buffer
|
||||
ret = AudioQueueEnqueueBuffer(consumer->queue, buffer, 0, NULL);
|
||||
AudioQueueEnqueueBuffer(consumer->queue, buffer, 0, NULL);
|
||||
// alert the jitter buffer
|
||||
tdav_consumer_audio_tick(TDAV_CONSUMER_AUDIO(consumer));
|
||||
}
|
||||
|
||||
/* ============ Media Consumer Interface ================= */
|
||||
|
@ -87,17 +82,17 @@ int tdav_consumer_audioqueue_prepare(tmedia_consumer_t* self, const tmedia_codec
|
|||
|
||||
// Create the audio stream description
|
||||
AudioStreamBasicDescription *description = &(consumer->description);
|
||||
description->mSampleRate = TDAV_CONSUMER_AUDIO(consumer)->output_rate ? TDAV_CONSUMER_AUDIO(consumer)->output_rate : TDAV_CONSUMER_AUDIO(consumer)->codec_rate;
|
||||
description->mSampleRate = TMEDIA_CONSUMER(consumer)->audio.out.rate ? TMEDIA_CONSUMER(consumer)->audio.out.rate : TMEDIA_CONSUMER(consumer)->audio.in.rate;
|
||||
description->mFormatID = kAudioFormatLinearPCM;
|
||||
description->mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
|
||||
description->mChannelsPerFrame = TDAV_CONSUMER_AUDIO(consumer)->channels;
|
||||
description->mChannelsPerFrame = TMEDIA_CONSUMER(consumer)->audio.in.channels;
|
||||
description->mFramesPerPacket = 1;
|
||||
description->mBitsPerChannel = TDAV_CONSUMER_AUDIO(consumer)->bits_per_sample;
|
||||
description->mBitsPerChannel = TMEDIA_CONSUMER(consumer)->audio.bits_per_sample;
|
||||
description->mBytesPerPacket = description->mBitsPerChannel / 8 * description->mChannelsPerFrame;
|
||||
description->mBytesPerFrame = description->mBytesPerPacket;
|
||||
description->mReserved = 0;
|
||||
|
||||
int packetperbuffer = 1000 / TDAV_CONSUMER_AUDIO(consumer)->ptime;
|
||||
int packetperbuffer = 1000 / TMEDIA_CONSUMER(consumer)->audio.ptime;
|
||||
consumer->buffer_size = description->mSampleRate * description->mBytesPerFrame / packetperbuffer;
|
||||
|
||||
// Create the playback audio queue
|
||||
|
@ -155,7 +150,7 @@ int tdav_consumer_audioqueue_consume(tmedia_consumer_t* self, const void* buffer
|
|||
{
|
||||
tdav_consumer_audioqueue_t* consumer = (tdav_consumer_audioqueue_t*)self;
|
||||
|
||||
if(!consumer || !buffer || !*buffer || !size){
|
||||
if(!consumer || !buffer || !size){
|
||||
TSK_DEBUG_ERROR("Invalid parameter");
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,22 @@
|
|||
|
||||
#if HAVE_COREAUDIO_AUDIO_UNIT
|
||||
|
||||
// AudioUnit already contains denoiser
|
||||
#if HAVE_SPEEX_DSP && (!defined(HAVE_SPEEX_DENOISE) || HAVE_SPEEX_DENOISE)
|
||||
# error "AudioUnit already contain denoiser => Disable it"
|
||||
#endif
|
||||
// FIXME: ONLY WORKS with SpeexJitterBuffer => add ifdef elif...
|
||||
|
||||
#undef DISABLE_JITTER_BUFFER
|
||||
#define DISABLE_JITTER_BUFFER 0 // FIXME: Find why there is too delay when we use speex jitter buffer
|
||||
|
||||
#include "tsk_debug.h"
|
||||
#include "tsk_memory.h"
|
||||
|
||||
#define kNoDataError -1
|
||||
#define kRingPacketCount +5
|
||||
|
||||
static tsk_size_t tdav_consumer_audiounit_get(tdav_consumer_audiounit_t* self, void* data, tsk_size_t size);
|
||||
|
||||
static OSStatus __handle_output_buffer(void *inRefCon,
|
||||
AudioUnitRenderActionFlags *ioActionFlags,
|
||||
|
@ -33,7 +48,50 @@ static OSStatus __handle_output_buffer(void *inRefCon,
|
|||
UInt32 inBusNumber,
|
||||
UInt32 inNumberFrames,
|
||||
AudioBufferList *ioData) {
|
||||
return noErr;
|
||||
OSStatus status = noErr;
|
||||
// tsk_size_t out_size;
|
||||
tdav_consumer_audiounit_t* consumer = (tdav_consumer_audiounit_t* )inRefCon;
|
||||
|
||||
if(!consumer->started || consumer->paused){
|
||||
goto done;
|
||||
}
|
||||
|
||||
if(!ioData){
|
||||
TSK_DEBUG_ERROR("Invalid argument");
|
||||
status = kNoDataError;
|
||||
goto done;
|
||||
}
|
||||
// read from jitter buffer and fill ioData buffers
|
||||
for(int i=0; i<ioData->mNumberBuffers; i++){
|
||||
/* int ret = */ tdav_consumer_audiounit_get(consumer, ioData->mBuffers[i].mData, ioData->mBuffers[i].mDataByteSize);
|
||||
}
|
||||
|
||||
done:
|
||||
#if !DISABLE_JITTER_BUFFER
|
||||
// alert the jitter buffer
|
||||
tdav_consumer_audio_tick(TDAV_CONSUMER_AUDIO(consumer));
|
||||
#endif
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static tsk_size_t tdav_consumer_audiounit_get(tdav_consumer_audiounit_t* self, void* data, tsk_size_t size)
|
||||
{
|
||||
tsk_ssize_t retSize = 0;
|
||||
#if DISABLE_JITTER_BUFFER
|
||||
retSize = speex_buffer_read(self->ring.buffer, data, size);
|
||||
if(retSize < size){
|
||||
memset(((uint8_t*)data)+retSize, 0, (size - retSize));
|
||||
}
|
||||
#else
|
||||
retSize = (tsk_ssize_t)tdav_consumer_audio_get(TDAV_CONSUMER_AUDIO(self), data, 370/*TSK_MIN(self->ring.chunck.size, size)*/);
|
||||
printf("size=%d\n", size);
|
||||
if(retSize < size){
|
||||
memset(((uint8_t*)data)+retSize, 0, (size - retSize));
|
||||
}
|
||||
#endif
|
||||
|
||||
return retSize;
|
||||
}
|
||||
|
||||
/* ============ Media Consumer Interface ================= */
|
||||
|
@ -42,6 +100,7 @@ static OSStatus __handle_output_buffer(void *inRefCon,
|
|||
static int tdav_consumer_audiounit_prepare(tmedia_consumer_t* self, const tmedia_codec_t* codec)
|
||||
{
|
||||
static UInt32 flagOne = 1;
|
||||
AudioStreamBasicDescription audioFormat;
|
||||
#define kOutputBus 0
|
||||
|
||||
tdav_consumer_audiounit_t* consumer = (tdav_consumer_audiounit_t*)self;
|
||||
|
@ -55,7 +114,7 @@ static int tdav_consumer_audiounit_prepare(tmedia_consumer_t* self, const tmedia
|
|||
TSK_DEBUG_ERROR("Already propared");
|
||||
return -2;
|
||||
}
|
||||
if(!(consumer->audioUnitHandle = tdav_audiounit_handle_create(TMEDIA_CONSUMER(consumer)->session_id))){
|
||||
if(!(consumer->audioUnitHandle = tdav_audiounit_handle_create(TMEDIA_CONSUMER(consumer)->session_id, codec->plugin->audio.ptime))){
|
||||
TSK_DEBUG_ERROR("Failed to get audio unit instance for session with id=%lld", TMEDIA_CONSUMER(consumer)->session_id);
|
||||
return -3;
|
||||
}
|
||||
|
@ -72,12 +131,12 @@ static int tdav_consumer_audiounit_prepare(tmedia_consumer_t* self, const tmedia
|
|||
return -4;
|
||||
}
|
||||
else {
|
||||
TMEDIA_CONSUMER(consumer)->audio.ptime = codec->plugin->audio.ptime;
|
||||
uint32_t frame_duration = tdav_audiounit_handle_get_frame_duration(consumer->audioUnitHandle);
|
||||
TMEDIA_CONSUMER(consumer)->audio.ptime = frame_duration ? frame_duration : codec->plugin->audio.ptime;
|
||||
TMEDIA_CONSUMER(consumer)->audio.in.channels = codec->plugin->audio.channels;
|
||||
TMEDIA_CONSUMER(consumer)->audio.in.rate = codec->plugin->rate;
|
||||
|
||||
|
||||
// set format
|
||||
AudioStreamBasicDescription audioFormat;
|
||||
audioFormat.mSampleRate = TMEDIA_CONSUMER(consumer)->audio.out.rate ? TMEDIA_CONSUMER(consumer)->audio.out.rate : TMEDIA_CONSUMER(consumer)->audio.in.rate;
|
||||
audioFormat.mFormatID = kAudioFormatLinearPCM;
|
||||
audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
|
||||
|
@ -93,6 +152,7 @@ static int tdav_consumer_audiounit_prepare(tmedia_consumer_t* self, const tmedia
|
|||
kOutputBus,
|
||||
&audioFormat,
|
||||
sizeof(audioFormat));
|
||||
|
||||
if(status){
|
||||
TSK_DEBUG_ERROR("AudioUnitSetProperty(kAudioUnitProperty_StreamFormat) failed with status=%d", (int32_t)status);
|
||||
return -5;
|
||||
|
@ -115,6 +175,46 @@ static int tdav_consumer_audiounit_prepare(tmedia_consumer_t* self, const tmedia
|
|||
}
|
||||
}
|
||||
|
||||
// allocate the chunck buffer and create the ring
|
||||
int packetperbuffer = (1000 / TMEDIA_CONSUMER(consumer)->audio.ptime);
|
||||
consumer->ring.chunck.size = audioFormat.mSampleRate * audioFormat.mBytesPerFrame / packetperbuffer;
|
||||
consumer->ring.size = kRingPacketCount * consumer->ring.chunck.size;
|
||||
if(!(consumer->ring.chunck.buffer = tsk_realloc(consumer->ring.chunck.buffer, consumer->ring.chunck.size))){
|
||||
TSK_DEBUG_ERROR("Failed to allocate new buffer");
|
||||
return -7;
|
||||
}
|
||||
if(!consumer->ring.buffer){
|
||||
consumer->ring.buffer = speex_buffer_init(consumer->ring.size);
|
||||
}
|
||||
else {
|
||||
int ret;
|
||||
if((ret = speex_buffer_resize(consumer->ring.buffer, consumer->ring.size))){
|
||||
TSK_DEBUG_ERROR("speex_buffer_resize(%d) failed with error code=%d", consumer->ring.size, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if(!consumer->ring.buffer){
|
||||
TSK_DEBUG_ERROR("Failed to create a new ring buffer with size = %d", consumer->ring.size);
|
||||
return -8;
|
||||
}
|
||||
if(!(consumer->ring.mutex = tsk_mutex_create())){
|
||||
TSK_DEBUG_ERROR("Failed to create mutex");
|
||||
return -9;
|
||||
}
|
||||
|
||||
// set maximum frames per slice as buffer size
|
||||
//UInt32 numFrames = (UInt32)consumer->ring.chunck.size;
|
||||
//status = AudioUnitSetProperty(tdav_audiounit_handle_get_instance(consumer->audioUnitHandle),
|
||||
// kAudioUnitProperty_MaximumFramesPerSlice,
|
||||
// kAudioUnitScope_Global,
|
||||
// 0,
|
||||
// &numFrames,
|
||||
// sizeof(numFrames));
|
||||
//if(status){
|
||||
// TSK_DEBUG_ERROR("AudioUnitSetProperty(kAudioUnitProperty_MaximumFramesPerSlice, %u) failed with status=%d", (unsigned)numFrames, (int32_t)status);
|
||||
// return -6;
|
||||
//}
|
||||
|
||||
TSK_DEBUG_INFO("AudioUnit producer prepared");
|
||||
return tdav_audiounit_handle_signal_consumer_prepared(consumer->audioUnitHandle);
|
||||
}
|
||||
|
@ -148,9 +248,36 @@ static int tdav_consumer_audiounit_start(tmedia_consumer_t* self)
|
|||
}
|
||||
|
||||
static int tdav_consumer_audiounit_consume(tmedia_consumer_t* self, const void* buffer, tsk_size_t size, const tsk_object_t* proto_hdr)
|
||||
{
|
||||
TSK_DEBUG_ERROR("Not implemented");
|
||||
return -1;
|
||||
{
|
||||
tdav_consumer_audiounit_t* consumer = (tdav_consumer_audiounit_t*)self;
|
||||
if(!consumer || !buffer || !size){
|
||||
TSK_DEBUG_ERROR("Invalid parameter");
|
||||
return -1;
|
||||
}
|
||||
#if DISABLE_JITTER_BUFFER
|
||||
{
|
||||
if(consumer->ring.buffer){
|
||||
tsk_mutex_lock(consumer->ring.mutex);
|
||||
speex_buffer_write(consumer->ring.buffer, (void*)buffer, size);
|
||||
tsk_mutex_unlock(consumer->ring.mutex);
|
||||
return 0;
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
#else
|
||||
{
|
||||
tsk_mutex_lock(consumer->ring.mutex);
|
||||
speex_buffer_write(consumer->ring.buffer, (void*)buffer, size);
|
||||
int avail = speex_buffer_get_available(consumer->ring.buffer);
|
||||
while (avail >= consumer->ring.chunck.size) {
|
||||
speex_buffer_read(consumer->ring.buffer, consumer->ring.chunck.buffer, consumer->ring.chunck.size);
|
||||
tdav_consumer_audio_put(TDAV_CONSUMER_AUDIO(consumer), consumer->ring.chunck.buffer, consumer->ring.chunck.size, proto_hdr);
|
||||
avail -= consumer->ring.chunck.size;
|
||||
}
|
||||
tsk_mutex_unlock(consumer->ring.mutex);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static int tdav_consumer_audiounit_pause(tmedia_consumer_t* self)
|
||||
|
@ -200,6 +327,7 @@ static tsk_object_t* tdav_consumer_audiounit_ctor(tsk_object_t * self, va_list *
|
|||
if(consumer){
|
||||
/* init base */
|
||||
tdav_consumer_audio_init(TDAV_CONSUMER_AUDIO(consumer));
|
||||
/* init self */
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
@ -208,6 +336,7 @@ static tsk_object_t* tdav_consumer_audiounit_dtor(tsk_object_t * self)
|
|||
{
|
||||
tdav_consumer_audiounit_t *consumer = self;
|
||||
if(consumer){
|
||||
/* deinit self */
|
||||
// Stop the consumer if not done
|
||||
if(consumer->started){
|
||||
tdav_consumer_audiounit_stop(self);
|
||||
|
@ -216,6 +345,13 @@ static tsk_object_t* tdav_consumer_audiounit_dtor(tsk_object_t * self)
|
|||
if(consumer->audioUnitHandle){
|
||||
tdav_audiounit_handle_destroy(&consumer->audioUnitHandle);
|
||||
}
|
||||
TSK_FREE(consumer->ring.chunck.buffer);
|
||||
if(consumer->ring.buffer){
|
||||
speex_buffer_destroy(consumer->ring.buffer);
|
||||
}
|
||||
if(consumer->ring.mutex){
|
||||
tsk_mutex_destroy(&consumer->ring.mutex);
|
||||
}
|
||||
|
||||
/* deinit base */
|
||||
tdav_consumer_audio_deinit(TDAV_CONSUMER_AUDIO(consumer));
|
||||
|
|
|
@ -41,7 +41,6 @@
|
|||
#include "tsk_debug.h"
|
||||
|
||||
static void __handle_input_buffer (void *userdata, AudioQueueRef queue, AudioQueueBufferRef buffer, const AudioTimeStamp *start_time, UInt32 number_packet_descriptions, const AudioStreamPacketDescription *packet_descriptions ) {
|
||||
OSStatus ret;
|
||||
tdav_producer_audioqueue_t* producer = (tdav_producer_audioqueue_t*)userdata;
|
||||
|
||||
if (!producer->started) {
|
||||
|
@ -54,7 +53,7 @@ static void __handle_input_buffer (void *userdata, AudioQueueRef queue, AudioQue
|
|||
}
|
||||
|
||||
// Re-enqueue the buffer
|
||||
ret = AudioQueueEnqueueBuffer(producer->queue, buffer, 0, NULL);
|
||||
AudioQueueEnqueueBuffer(producer->queue, buffer, 0, NULL);
|
||||
}
|
||||
|
||||
/* ============ Media Producer Interface ================= */
|
||||
|
@ -83,7 +82,7 @@ static int tdav_producer_audioqueue_prepare(tmedia_producer_t* self, const tmedi
|
|||
|
||||
// Create the audio stream description
|
||||
AudioStreamBasicDescription *description = &(producer->description);
|
||||
description->mSampleRate = TMEDIA_PRODUCER(producer)->audio.rate
|
||||
description->mSampleRate = TMEDIA_PRODUCER(producer)->audio.rate;
|
||||
description->mFormatID = kAudioFormatLinearPCM;
|
||||
description->mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
|
||||
description->mChannelsPerFrame = TMEDIA_PRODUCER(producer)->audio.channels;
|
||||
|
@ -93,7 +92,7 @@ static int tdav_producer_audioqueue_prepare(tmedia_producer_t* self, const tmedi
|
|||
description->mBytesPerFrame = description->mBytesPerPacket;
|
||||
description->mReserved = 0;
|
||||
|
||||
int packetperbuffer = 1000 / TDAV_PRODUCER_AUDIO(producer)->ptime;
|
||||
int packetperbuffer = 1000 / TMEDIA_PRODUCER(producer)->audio.ptime;
|
||||
producer->buffer_size = description->mSampleRate * description->mBytesPerFrame / packetperbuffer;
|
||||
|
||||
// Create the record audio queue
|
||||
|
|
|
@ -25,15 +25,57 @@
|
|||
|
||||
#if HAVE_COREAUDIO_AUDIO_UNIT
|
||||
|
||||
// AudioUnit already contains denoiser
|
||||
#if HAVE_SPEEX_DSP && (!defined(HAVE_SPEEX_DENOISE) || HAVE_SPEEX_DENOISE)
|
||||
# error "AudioUnit already contain denoiser => Disable it"
|
||||
#endif
|
||||
|
||||
#include "tsk_memory.h"
|
||||
#include "tsk_debug.h"
|
||||
|
||||
#define kRingPacketCount +3
|
||||
|
||||
static OSStatus __handle_input_buffer(void *inRefCon,
|
||||
AudioUnitRenderActionFlags *ioActionFlags,
|
||||
const AudioTimeStamp *inTimeStamp,
|
||||
UInt32 inBusNumber,
|
||||
UInt32 inNumberFrames,
|
||||
AudioBufferList *ioData) {
|
||||
return noErr;
|
||||
OSStatus status = noErr;
|
||||
tdav_producer_audiounit_t* producer = (tdav_producer_audiounit_t*)inRefCon;
|
||||
|
||||
// holder
|
||||
AudioBuffer buffer;
|
||||
buffer.mData = tsk_null;
|
||||
buffer.mDataByteSize = 0;
|
||||
|
||||
// list of holders
|
||||
AudioBufferList buffers;
|
||||
buffers.mNumberBuffers = 1;
|
||||
buffers.mBuffers[0] = buffer;
|
||||
|
||||
// render to get frames from the system
|
||||
status = AudioUnitRender(tdav_audiounit_handle_get_instance(producer->audioUnitHandle),
|
||||
ioActionFlags,
|
||||
inTimeStamp,
|
||||
inBusNumber,
|
||||
inNumberFrames,
|
||||
&buffers);
|
||||
if(!status){
|
||||
// Alert the session that there is new data to send
|
||||
if(TMEDIA_PRODUCER(producer)->enc_cb.callback) {
|
||||
speex_buffer_write(producer->ring.buffer, buffers.mBuffers[0].mData, buffers.mBuffers[0].mDataByteSize);
|
||||
tsk_ssize_t avail = speex_buffer_get_available(producer->ring.buffer);
|
||||
while (avail >= producer->ring.chunck.size) {
|
||||
tsk_size_t read = speex_buffer_read(producer->ring.buffer, producer->ring.chunck.buffer, producer->ring.chunck.size);
|
||||
TMEDIA_PRODUCER(producer)->enc_cb.callback(TMEDIA_PRODUCER(producer)->enc_cb.callback_data,
|
||||
producer->ring.chunck.buffer, producer->ring.chunck.size);
|
||||
avail -= read;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* ============ Media Producer Interface ================= */
|
||||
|
@ -42,11 +84,12 @@ static OSStatus __handle_input_buffer(void *inRefCon,
|
|||
static int tdav_producer_audiounit_prepare(tmedia_producer_t* self, const tmedia_codec_t* codec)
|
||||
{
|
||||
static UInt32 flagOne = 1;
|
||||
static UInt32 flagZero = 0;
|
||||
// static UInt32 flagZero = 0;
|
||||
#define kInputBus 1
|
||||
|
||||
tdav_producer_audiounit_t* producer = (tdav_producer_audiounit_t*)self;
|
||||
OSStatus status;
|
||||
AudioStreamBasicDescription audioFormat;
|
||||
|
||||
if(!producer || !codec || !codec->plugin){
|
||||
TSK_DEBUG_ERROR("Invalid parameter");
|
||||
|
@ -56,7 +99,7 @@ static int tdav_producer_audiounit_prepare(tmedia_producer_t* self, const tmedia
|
|||
TSK_DEBUG_ERROR("Already propared");
|
||||
return -2;
|
||||
}
|
||||
if(!(producer->audioUnitHandle = tdav_audiounit_handle_create(TMEDIA_PRODUCER(producer)->session_id))){
|
||||
if(!(producer->audioUnitHandle = tdav_audiounit_handle_create(TMEDIA_PRODUCER(producer)->session_id, codec->plugin->audio.ptime))){
|
||||
TSK_DEBUG_ERROR("Failed to get audio unit instance for session with id=%lld", TMEDIA_PRODUCER(producer)->session_id);
|
||||
return -3;
|
||||
}
|
||||
|
@ -79,7 +122,6 @@ static int tdav_producer_audiounit_prepare(tmedia_producer_t* self, const tmedia
|
|||
/* codec should have ptime */
|
||||
|
||||
// set format
|
||||
AudioStreamBasicDescription audioFormat;
|
||||
audioFormat.mSampleRate = TMEDIA_PRODUCER(producer)->audio.rate;
|
||||
audioFormat.mFormatID = kAudioFormatLinearPCM;
|
||||
audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
|
||||
|
@ -116,17 +158,41 @@ static int tdav_producer_audiounit_prepare(tmedia_producer_t* self, const tmedia
|
|||
}
|
||||
else {
|
||||
// disbale buffer allocation as we will provide ours
|
||||
status = AudioUnitSetProperty(tdav_audiounit_handle_get_instance(producer->audioUnitHandle),
|
||||
kAudioUnitProperty_ShouldAllocateBuffer,
|
||||
kAudioUnitScope_Output,
|
||||
kInputBus,
|
||||
&flagZero,
|
||||
sizeof(flagZero));
|
||||
//status = AudioUnitSetProperty(tdav_audiounit_handle_get_instance(producer->audioUnitHandle),
|
||||
// kAudioUnitProperty_ShouldAllocateBuffer,
|
||||
// kAudioUnitScope_Output,
|
||||
// kInputBus,
|
||||
// &flagZero,
|
||||
// sizeof(flagZero));
|
||||
|
||||
int packetperbuffer = (1000 / codec->plugin->audio.ptime);
|
||||
producer->ring.chunck.size = audioFormat.mSampleRate * audioFormat.mBytesPerFrame / packetperbuffer;
|
||||
// allocate our chunck buffer
|
||||
if(!(producer->ring.chunck.buffer = tsk_realloc(producer->ring.chunck.buffer, producer->ring.chunck.size))){
|
||||
TSK_DEBUG_ERROR("Failed to allocate new buffer");
|
||||
return -7;
|
||||
}
|
||||
// create ringbuffer
|
||||
producer->ring.size = kRingPacketCount * producer->ring.chunck.size;
|
||||
if(!producer->ring.buffer){
|
||||
producer->ring.buffer = speex_buffer_init(producer->ring.size);
|
||||
}
|
||||
else {
|
||||
int ret;
|
||||
if((ret = speex_buffer_resize(producer->ring.buffer, producer->ring.size))){
|
||||
TSK_DEBUG_ERROR("speex_buffer_resize(%d) failed with error code=%d", producer->ring.size, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if(!producer->ring.buffer){
|
||||
TSK_DEBUG_ERROR("Failed to create a new ring buffer with size = %d", producer->ring.size);
|
||||
return -8;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TSK_DEBUG_INFO("AudioUnit producer prepared");
|
||||
return tdav_audiounit_handle_signal_producer_prepared(producer->audioUnitHandle);;
|
||||
}
|
||||
|
@ -224,7 +290,10 @@ static tsk_object_t* tdav_producer_audiounit_dtor(tsk_object_t * self)
|
|||
if (producer->audioUnitHandle) {
|
||||
tdav_audiounit_handle_destroy(&producer->audioUnitHandle);
|
||||
}
|
||||
|
||||
TSK_FREE(producer->ring.chunck.buffer);
|
||||
if(producer->ring.buffer){
|
||||
speex_buffer_destroy(producer->ring.buffer);
|
||||
}
|
||||
/* deinit base */
|
||||
tdav_producer_audio_deinit(TDAV_PRODUCER_AUDIO(producer));
|
||||
}
|
||||
|
|
|
@ -161,7 +161,9 @@ tsk_size_t tdav_consumer_audio_get(tdav_consumer_audio_t* self, void* out_data,
|
|||
|
||||
if(!TMEDIA_JITTER_BUFFER(self->jitterbuffer)->opened){
|
||||
int ret;
|
||||
if((ret = tmedia_jitterbuffer_open(TMEDIA_JITTER_BUFFER(self->jitterbuffer), TMEDIA_CONSUMER(self)->audio.ptime, TMEDIA_CONSUMER(self)->audio.in.rate))){
|
||||
uint32_t frame_duration = TMEDIA_CONSUMER(self)->audio.ptime;
|
||||
uint32_t rate = TMEDIA_CONSUMER(self)->audio.in.rate;
|
||||
if((ret = tmedia_jitterbuffer_open(TMEDIA_JITTER_BUFFER(self->jitterbuffer), frame_duration, rate))){
|
||||
TSK_DEBUG_ERROR("Failed to open jitterbuffer (%d)", ret);
|
||||
tsk_safeobj_unlock(self);
|
||||
return 0;
|
||||
|
|
|
@ -296,16 +296,14 @@ int tdav_session_audio_start(tmedia_session_t* self)
|
|||
//trtp_manager_set_payload_type(audio->rtp_manager, codec->neg_format ? atoi(codec->neg_format) : atoi(codec->format));
|
||||
ret = trtp_manager_start(audio->rtp_manager);
|
||||
|
||||
/* Consumer */
|
||||
if(audio->consumer){
|
||||
tmedia_consumer_prepare(audio->consumer, codec);
|
||||
tmedia_consumer_start(audio->consumer);
|
||||
}
|
||||
/* Producer */
|
||||
if(audio->producer){
|
||||
tmedia_producer_prepare(audio->producer, codec);
|
||||
tmedia_producer_start(audio->producer);
|
||||
}
|
||||
// because of AudioUnit under iOS => prepare both consumer and producer then start() at the same time
|
||||
/* prepare consumer and producer */
|
||||
if(audio->consumer) tmedia_consumer_prepare(audio->consumer, codec);
|
||||
if(audio->producer) tmedia_producer_prepare(audio->producer, codec);
|
||||
/* start consumer and producer */
|
||||
if(audio->consumer) tmedia_consumer_start(audio->consumer);
|
||||
if(audio->producer) tmedia_producer_start(audio->producer);
|
||||
|
||||
/* Denoise (AEC, Noise Suppression, AGC) */
|
||||
if(audio->denoise && audio->encoder.codec){
|
||||
tmedia_denoise_open(audio->denoise, TMEDIA_CODEC_PCM_FRAME_SIZE(audio->encoder.codec), TMEDIA_CODEC_RATE(audio->encoder.codec), tsk_true, 8000.0f, tsk_true, tsk_true);
|
||||
|
@ -784,11 +782,15 @@ static tsk_object_t* tdav_session_audio_ctor(tsk_object_t * self, va_list * app)
|
|||
if(session){
|
||||
/* init base: called by tmedia_session_create() */
|
||||
/* init self */
|
||||
uint64_t session_id = TMEDIA_SESSION(session)->id;
|
||||
tsk_safeobj_init(session);
|
||||
if(!(session->consumer = tmedia_consumer_create(tdav_session_audio_plugin_def_t->type, TMEDIA_SESSION(session)->id))){
|
||||
if(!session_id){ // set the session id if not already done
|
||||
TMEDIA_SESSION(session)->id = session_id = tmedia_session_get_unique_id();
|
||||
}
|
||||
if(!(session->consumer = tmedia_consumer_create(tdav_session_audio_plugin_def_t->type, session_id))){
|
||||
TSK_DEBUG_ERROR("Failed to create Audio consumer");
|
||||
}
|
||||
if((session->producer = tmedia_producer_create(tdav_session_audio_plugin_def_t->type, TMEDIA_SESSION(session)->id))){
|
||||
if((session->producer = tmedia_producer_create(tdav_session_audio_plugin_def_t->type, session_id))){
|
||||
tmedia_producer_set_enc_callback(session->producer, tdav_session_audio_producer_enc_cb, self);
|
||||
}
|
||||
else{
|
||||
|
|
|
@ -49,7 +49,7 @@ static int _10ms_size_bytes = 160;
|
|||
#define TDAV_SPEAKUP_10MS_FRAME_SIZE(self) (((self)->rate * TDAV_SPEAKUP_10MS)/1000)
|
||||
#define TDAV_SPEAKUP_PTIME_FRAME_SIZE(self) (((self)->rate * (self)->framesize)/1000)
|
||||
|
||||
int tdav_speakup_jitterbuffer_open(tmedia_jitterbuffer_t* self, uint32_t framesize, uint32_t rate)
|
||||
int tdav_speakup_jitterbuffer_open(tmedia_jitterbuffer_t* self, uint32_t frame_duration, uint32_t rate)
|
||||
{
|
||||
tdav_speakup_jitterbuffer_t *jitterbuffer = (tdav_speakup_jitterbuffer_t *)self;
|
||||
if(!jitterbuffer->jbuffer){
|
||||
|
@ -60,7 +60,7 @@ int tdav_speakup_jitterbuffer_open(tmedia_jitterbuffer_t* self, uint32_t framesi
|
|||
jitterbuffer->jcodec = JB_CODEC_OTHER;
|
||||
}
|
||||
jitterbuffer->ref_timestamp = 0;
|
||||
jitterbuffer->framesize = framesize;
|
||||
jitterbuffer->frame_duration = frame_duration;
|
||||
jitterbuffer->rate = rate;
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
#include "tsk_memory.h"
|
||||
#include "tsk_debug.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define ECHO_TAIL 20
|
||||
|
||||
int tdav_speex_denoise_open(tmedia_denoise_t* self, uint32_t frame_size, uint32_t sampling_rate, tsk_bool_t denoise, float agc_level, tsk_bool_t aec, tsk_bool_t vad)
|
||||
|
|
|
@ -35,14 +35,15 @@
|
|||
#include "tsk_debug.h"
|
||||
|
||||
|
||||
int tdav_speex_jitterbuffer_open(tmedia_jitterbuffer_t* self, uint32_t framesize, uint32_t rate)
|
||||
int tdav_speex_jitterbuffer_open(tmedia_jitterbuffer_t* self, uint32_t frame_duration, uint32_t rate)
|
||||
{
|
||||
tdav_speex_jitterbuffer_t *jitterbuffer = (tdav_speex_jitterbuffer_t *)self;
|
||||
if(!(jitterbuffer->state = jitter_buffer_init((int)framesize))){
|
||||
if(!(jitterbuffer->state = jitter_buffer_init((int)frame_duration))){
|
||||
TSK_DEBUG_ERROR("jitter_buffer_init() failed");
|
||||
return -2;
|
||||
}
|
||||
jitterbuffer->rate = rate;
|
||||
jitterbuffer->frame_duration = frame_duration;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -78,7 +79,7 @@ int tdav_speex_jitterbuffer_put(tmedia_jitterbuffer_t* self, void* data, tsk_siz
|
|||
jb_packet.data = data;
|
||||
jb_packet.len = data_size;
|
||||
jb_packet.span = (data_size*500)/jitterbuffer->rate;
|
||||
jb_packet.timestamp = (rtp_hdr->seq_num*jb_packet.span);
|
||||
jb_packet.timestamp = (rtp_hdr->seq_num * jb_packet.span);
|
||||
|
||||
jb_packet.sequence = rtp_hdr->seq_num;
|
||||
jb_packet.user_data = 0;
|
||||
|
@ -107,13 +108,14 @@ tsk_size_t tdav_speex_jitterbuffer_get(tmedia_jitterbuffer_t* self, void* out_da
|
|||
|
||||
if ((ret = jitter_buffer_get(jitterbuffer->state, &jb_packet, (out_size*500)/jitterbuffer->rate, tsk_null)) != JITTER_BUFFER_OK) {
|
||||
switch(ret){
|
||||
case JITTER_BUFFER_MISSING: /*TSK_DEBUG_INFO("JITTER_BUFFER_MISSING - %d", ret);*/ break;
|
||||
case JITTER_BUFFER_MISSING: /*TSK_DEBUG_INFO("JITTER_BUFFER_MISSING - %d", ret);*/ break;
|
||||
case JITTER_BUFFER_INSERTION: /*TSK_DEBUG_INFO("JITTER_BUFFER_INSERTION - %d", ret);*/ break;
|
||||
default: TSK_DEBUG_INFO("jitter_buffer_get() failed - %d", ret);
|
||||
}
|
||||
// jitter_buffer_update_delay(jitterbuffer->state, &jb_packet, NULL);
|
||||
return 0;
|
||||
}
|
||||
jitter_buffer_update_delay(jitterbuffer->state, &jb_packet, NULL);
|
||||
|
||||
return out_size;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,12 @@
|
|||
*/
|
||||
#include "tinydav/tdav.h"
|
||||
|
||||
#if TDAV_UNDER_WINDOWS
|
||||
# include "tinydav/tdav_win32.h"
|
||||
#elif TDAV_UNDER_APPLE
|
||||
# include "tinydav/tdav_apple.h"
|
||||
#endif
|
||||
|
||||
// Media Contents, ...
|
||||
#include "tinymedia.h"
|
||||
|
||||
|
@ -94,6 +100,19 @@
|
|||
|
||||
int tdav_init()
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
/* === OS specific === */
|
||||
#if TDAV_UNDER_WINDOWS
|
||||
if ((ret = tdav_win32_init())) {
|
||||
return ret;
|
||||
}
|
||||
#elif TDAV_UNDER_APPLE
|
||||
if ((ret = tdav_apple_init())) {
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* === Initialize ffmpeg === */
|
||||
#if HAVE_FFMPEG
|
||||
avcodec_init();
|
||||
|
@ -219,7 +238,7 @@ int tdav_init()
|
|||
tmedia_jitterbuffer_plugin_register(tdav_speakup_jitterbuffer_plugin_def_t);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
typedef struct tdav_codec_decl_s{
|
||||
|
@ -370,6 +389,19 @@ tsk_bool_t tdav_codec_is_supported(tdav_codec_id_t codec)
|
|||
|
||||
int tdav_deinit()
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
/* === OS specific === */
|
||||
#if TDAV_UNDER_WINDOWS
|
||||
if ((ret = tdav_win32_deinit())) {
|
||||
return ret;
|
||||
}
|
||||
#elif TDAV_UNDER_APPLE
|
||||
if ((ret = tdav_apple_deinit())) {
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* === UnRegister media contents === */
|
||||
tmedia_content_plugin_unregister_all();
|
||||
|
||||
|
@ -470,5 +502,5 @@ int tdav_deinit()
|
|||
tmedia_jitterbuffer_plugin_unregister(tdav_speakup_jitterbuffer_plugin_def_t);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
|
@ -32,6 +32,11 @@
|
|||
|
||||
#include "tsk_debug.h"
|
||||
|
||||
int tdav_win32_init()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tdav_win32_print_error(const char* func, HRESULT hr)
|
||||
{
|
||||
CHAR* message = tsk_null;
|
||||
|
@ -54,5 +59,9 @@ void tdav_win32_print_error(const char* func, HRESULT hr)
|
|||
LocalFree(message);
|
||||
}
|
||||
|
||||
int tdav_win32_deinit()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* TDAV_UNDER_WINDOWS */
|
|
@ -59,7 +59,7 @@ typedef struct tmedia_jitterbuffer_plugin_def_s
|
|||
//! full description (usefull for debugging)
|
||||
const char* desc;
|
||||
|
||||
int (* open) (tmedia_jitterbuffer_t*, uint32_t framesize, uint32_t rate);
|
||||
int (* open) (tmedia_jitterbuffer_t*, uint32_t frame_duration, uint32_t rate);
|
||||
int (* tick) (tmedia_jitterbuffer_t*);
|
||||
int (* put) (tmedia_jitterbuffer_t*, void* data, tsk_size_t data_size, const tsk_object_t* proto_hdr);
|
||||
tsk_size_t (* get) (tmedia_jitterbuffer_t*, void* out_data, tsk_size_t out_size);
|
||||
|
@ -69,7 +69,7 @@ typedef struct tmedia_jitterbuffer_plugin_def_s
|
|||
tmedia_jitterbuffer_plugin_def_t;
|
||||
|
||||
TINYMEDIA_API int tmedia_jitterbuffer_init(tmedia_jitterbuffer_t* self);
|
||||
TINYMEDIA_API int tmedia_jitterbuffer_open(tmedia_jitterbuffer_t* self, uint32_t framesize, uint32_t rate);
|
||||
TINYMEDIA_API int tmedia_jitterbuffer_open(tmedia_jitterbuffer_t* self, uint32_t frame_duration, uint32_t rate);
|
||||
TINYMEDIA_API int tmedia_jitterbuffer_tick(tmedia_jitterbuffer_t* self);
|
||||
TINYMEDIA_API int tmedia_jitterbuffer_put(tmedia_jitterbuffer_t* self, void* data, tsk_size_t data_size, const tsk_object_t* proto_hdr);
|
||||
TINYMEDIA_API tsk_size_t tmedia_jitterbuffer_get(tmedia_jitterbuffer_t* self, void* out_data, tsk_size_t out_size);
|
||||
|
|
|
@ -57,7 +57,7 @@ typedef struct tmedia_session_s
|
|||
{
|
||||
TSK_DECLARE_OBJECT;
|
||||
|
||||
//! unique id
|
||||
//! unique id. If you want to modifiy this field then you must use @ref tmedia_session_get_unique_id()
|
||||
uint64_t id;
|
||||
//! session type
|
||||
tmedia_type_t type;
|
||||
|
@ -113,6 +113,7 @@ typedef struct tmedia_session_plugin_def_s
|
|||
}
|
||||
tmedia_session_plugin_def_t;
|
||||
|
||||
TINYMEDIA_API uint64_t tmedia_session_get_unique_id();
|
||||
TINYMEDIA_API int tmedia_session_init(tmedia_session_t* self, tmedia_type_t type);
|
||||
TINYMEDIA_API int tmedia_session_cmp(const tsk_object_t* sess1, const tsk_object_t* sess2);
|
||||
TINYMEDIA_API int tmedia_session_plugin_register(const tmedia_session_plugin_def_t* plugin);
|
||||
|
|
|
@ -40,7 +40,7 @@ int tmedia_jitterbuffer_init(tmedia_jitterbuffer_t* self)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int tmedia_jitterbuffer_open(tmedia_jitterbuffer_t* self, uint32_t framesize, uint32_t rate)
|
||||
int tmedia_jitterbuffer_open(tmedia_jitterbuffer_t* self, uint32_t frame_duration, uint32_t rate)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -53,7 +53,7 @@ int tmedia_jitterbuffer_open(tmedia_jitterbuffer_t* self, uint32_t framesize, ui
|
|||
return 0;
|
||||
}
|
||||
|
||||
if((ret = self->plugin->open(self, framesize, rate))){
|
||||
if((ret = self->plugin->open(self, frame_duration, rate))){
|
||||
TSK_DEBUG_ERROR("Failed to open [%s] jitterbufferr", self->plugin->desc);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -79,6 +79,11 @@ int __pred_find_session_by_type(const tsk_list_item_t *item, const void *type)
|
|||
return -1;
|
||||
}
|
||||
|
||||
uint64_t tmedia_session_get_unique_id(){
|
||||
static uint64_t __UniqueId = 1; // MUST not be equal to zero
|
||||
return __UniqueId++;
|
||||
}
|
||||
|
||||
/**@ingroup tmedia_session_group
|
||||
* Initializes a newly created media session.
|
||||
* @param self the media session to initialize.
|
||||
|
@ -88,7 +93,6 @@ int __pred_find_session_by_type(const tsk_list_item_t *item, const void *type)
|
|||
int tmedia_session_init(tmedia_session_t* self, tmedia_type_t type)
|
||||
{
|
||||
int ret = 0;
|
||||
static uint64_t __UniqueId = 1;
|
||||
|
||||
if(!self){
|
||||
TSK_DEBUG_ERROR("Invalid parameter");
|
||||
|
@ -97,7 +101,9 @@ int tmedia_session_init(tmedia_session_t* self, tmedia_type_t type)
|
|||
|
||||
if(!self->initialized){
|
||||
/* set values */
|
||||
self->id = ++__UniqueId;
|
||||
if(!self->id){
|
||||
self->id = tmedia_session_get_unique_id();
|
||||
}
|
||||
self->type = type;
|
||||
self->initialized = tsk_true;
|
||||
self->bl = tmedia_bl_low;
|
||||
|
|
|
@ -186,7 +186,7 @@ int c0000_Outgoing_2_Connected_X_i2xxINVITE(va_list *app)
|
|||
|
||||
tsip_dialog_invite_t *self = va_arg(*app, tsip_dialog_invite_t *);
|
||||
const tsip_response_t *r2xxINVITE = va_arg(*app, const tsip_response_t *);
|
||||
const tsip_action_t* action = va_arg(*app, const tsip_action_t *);
|
||||
/* const tsip_action_t* action = */ va_arg(*app, const tsip_action_t *);
|
||||
|
||||
/* Update the dialog state */
|
||||
if((ret = tsip_dialog_update(TSIP_DIALOG(self), r2xxINVITE))){
|
||||
|
|
Loading…
Reference in New Issue