2 channel audio can now be sent to groupchats.

Some cleanups and added comments.
This commit is contained in:
irungentoo 2014-11-11 14:39:25 -05:00
parent a8f670bd68
commit 8c0225b27f
No known key found for this signature in database
GPG Key ID: 10349DC9BED89E98
3 changed files with 80 additions and 23 deletions

View File

@ -158,35 +158,37 @@ typedef struct {
static void kill_group_av(Group_AV *group_av) static void kill_group_av(Group_AV *group_av)
{ {
if (group_av->audio_encoder) {
opus_encoder_destroy(group_av->audio_encoder); opus_encoder_destroy(group_av->audio_encoder);
}
free(group_av); free(group_av);
} }
static Group_AV *new_group_av(Group_Chats *g_c, unsigned int audio_channels, unsigned int audio_sample_rate, static int recreate_encoder(Group_AV *group_av)
unsigned int audio_bitrate, void (*audio_callback)(Messenger *, int, int, const int16_t *, unsigned int, uint8_t,
unsigned int, void *), void *userdata)
{ {
if (!g_c) if (group_av->audio_encoder) {
return NULL; opus_encoder_destroy(group_av->audio_encoder);
group_av->audio_encoder = NULL;
Group_AV *group_av = calloc(1, sizeof(Group_AV)); }
int rc = OPUS_OK; int rc = OPUS_OK;
group_av->audio_encoder = opus_encoder_create(audio_sample_rate, audio_channels, OPUS_APPLICATION_AUDIO, &rc); group_av->audio_encoder = opus_encoder_create(group_av->audio_sample_rate, group_av->audio_channels,
OPUS_APPLICATION_AUDIO, &rc);
if ( rc != OPUS_OK ) { if ( rc != OPUS_OK ) {
LOGGER_ERROR("Error while starting audio encoder: %s", opus_strerror(rc)); LOGGER_ERROR("Error while starting audio encoder: %s", opus_strerror(rc));
free(group_av); group_av->audio_encoder = NULL;
return NULL; return -1;
} }
rc = opus_encoder_ctl(group_av->audio_encoder, OPUS_SET_BITRATE(audio_bitrate)); rc = opus_encoder_ctl(group_av->audio_encoder, OPUS_SET_BITRATE(group_av->audio_bitrate));
if ( rc != OPUS_OK ) { if ( rc != OPUS_OK ) {
LOGGER_ERROR("Error while setting encoder ctl: %s", opus_strerror(rc)); LOGGER_ERROR("Error while setting encoder ctl: %s", opus_strerror(rc));
opus_encoder_destroy(group_av->audio_encoder); opus_encoder_destroy(group_av->audio_encoder);
free(group_av); group_av->audio_encoder = NULL;
return NULL; return -1;
} }
rc = opus_encoder_ctl(group_av->audio_encoder, OPUS_SET_COMPLEXITY(10)); rc = opus_encoder_ctl(group_av->audio_encoder, OPUS_SET_COMPLEXITY(10));
@ -194,17 +196,29 @@ static Group_AV *new_group_av(Group_Chats *g_c, unsigned int audio_channels, uns
if ( rc != OPUS_OK ) { if ( rc != OPUS_OK ) {
LOGGER_ERROR("Error while setting encoder ctl: %s", opus_strerror(rc)); LOGGER_ERROR("Error while setting encoder ctl: %s", opus_strerror(rc));
opus_encoder_destroy(group_av->audio_encoder); opus_encoder_destroy(group_av->audio_encoder);
free(group_av); group_av->audio_encoder = NULL;
return NULL; return -1;
} }
group_av->audio_channels = audio_channels; return 0;
group_av->audio_sample_rate = audio_sample_rate; }
group_av->audio_bitrate = audio_bitrate;
static Group_AV *new_group_av(Group_Chats *g_c, void (*audio_callback)(Messenger *, int, int, const int16_t *,
unsigned int, uint8_t, unsigned int, void *), void *userdata)
{
if (!g_c)
return NULL;
Group_AV *group_av = calloc(1, sizeof(Group_AV));
if (!group_av)
return NULL;
group_av->g_c = g_c; group_av->g_c = g_c;
group_av->audio_data = audio_callback; group_av->audio_data = audio_callback;
group_av->userdata = userdata; group_av->userdata = userdata;
return group_av; return group_av;
} }
@ -248,6 +262,8 @@ static int decode_audio_packet(Group_AV *group_av, Group_Peer_AV *peer_av, int g
int16_t *out_audio = NULL; int16_t *out_audio = NULL;
unsigned int out_audio_samples = 0; unsigned int out_audio_samples = 0;
unsigned int sample_rate = 48000;
if (success == 1) { if (success == 1) {
int channels = opus_packet_get_nb_channels(pk->data); int channels = opus_packet_get_nb_channels(pk->data);
@ -268,7 +284,7 @@ static int decode_audio_packet(Group_AV *group_av, Group_Peer_AV *peer_av, int g
} }
int rc; int rc;
peer_av->audio_decoder = opus_decoder_create(group_av->audio_sample_rate, channels, &rc); peer_av->audio_decoder = opus_decoder_create(sample_rate, channels, &rc);
if ( rc != OPUS_OK ) { if ( rc != OPUS_OK ) {
LOGGER_ERROR("Error while starting audio decoder: %s", opus_strerror(rc)); LOGGER_ERROR("Error while starting audio decoder: %s", opus_strerror(rc));
@ -320,7 +336,7 @@ static int decode_audio_packet(Group_AV *group_av, Group_Peer_AV *peer_av, int g
if (group_av->audio_data) if (group_av->audio_data)
group_av->audio_data(group_av->g_c->m, groupnumber, friendgroupnumber, out_audio, out_audio_samples, group_av->audio_data(group_av->g_c->m, groupnumber, friendgroupnumber, out_audio, out_audio_samples,
peer_av->decoder_channels, group_av->audio_sample_rate, group_av->userdata); peer_av->decoder_channels, sample_rate, group_av->userdata);
free(out_audio); free(out_audio);
return 0; return 0;
@ -371,7 +387,7 @@ static int groupchat_enable_av(Group_Chats *g_c, int groupnumber, void (*audio_c
if (groupnumber == -1) if (groupnumber == -1)
return -1; return -1;
Group_AV *group_av = new_group_av(g_c, 1, 48000, 64000, audio_callback, userdata); //TODO: Use variables instead. Group_AV *group_av = new_group_av(g_c, audio_callback, userdata);
if (group_av == NULL) if (group_av == NULL)
return -1; return -1;
@ -465,12 +481,27 @@ static int send_audio_packet(Group_Chats *g_c, int groupnumber, uint8_t *packet,
int group_send_audio(Group_Chats *g_c, int groupnumber, const int16_t *pcm, unsigned int samples, uint8_t channels, int group_send_audio(Group_Chats *g_c, int groupnumber, const int16_t *pcm, unsigned int samples, uint8_t channels,
unsigned int sample_rate) unsigned int sample_rate)
{ {
//TODO use channels and sample_rate arguments.
Group_AV *group_av = group_get_object(g_c, groupnumber); Group_AV *group_av = group_get_object(g_c, groupnumber);
if (!group_av) if (!group_av)
return -1; return -1;
if (channels != 1 && channels != 2)
return -1;
//TODO: allow different sample rates
if (sample_rate != 48000)
return -1;
if (!group_av->audio_encoder || group_av->audio_channels != channels || group_av->audio_sample_rate != sample_rate) {
group_av->audio_channels = channels;
group_av->audio_sample_rate = sample_rate;
group_av->audio_bitrate = 64000; //TODO: add way of adjusting bitrate
if (recreate_encoder(group_av) == -1)
return -1;
}
uint8_t encoded[1024]; uint8_t encoded[1024];
int32_t size = opus_encode(group_av->audio_encoder, pcm, samples, encoded, sizeof(encoded)); int32_t size = opus_encode(group_av->audio_encoder, pcm, samples, encoded, sizeof(encoded));

View File

@ -1160,6 +1160,8 @@ end:
* *
* Audio data callback format: * Audio data callback format:
* audio_callback(Tox *tox, int groupnumber, int peernumber, const int16_t *pcm, unsigned int samples, uint8_t channels, unsigned int sample_rate, void *userdata) * audio_callback(Tox *tox, int groupnumber, int peernumber, const int16_t *pcm, unsigned int samples, uint8_t channels, unsigned int sample_rate, void *userdata)
*
* Note that total size of pcm in bytes is equal to (samples * channels * sizeof(int16_t)).
*/ */
int toxav_add_av_groupchat(Tox *tox, void (*audio_callback)(Messenger *, int, int, const int16_t *, unsigned int, int toxav_add_av_groupchat(Tox *tox, void (*audio_callback)(Messenger *, int, int, const int16_t *, unsigned int,
uint8_t, unsigned int, void *), void *userdata) uint8_t, unsigned int, void *), void *userdata)
@ -1175,6 +1177,8 @@ int toxav_add_av_groupchat(Tox *tox, void (*audio_callback)(Messenger *, int, in
* *
* Audio data callback format (same as the one for toxav_add_av_groupchat()): * Audio data callback format (same as the one for toxav_add_av_groupchat()):
* audio_callback(Tox *tox, int groupnumber, int peernumber, const int16_t *pcm, unsigned int samples, uint8_t channels, unsigned int sample_rate, void *userdata) * audio_callback(Tox *tox, int groupnumber, int peernumber, const int16_t *pcm, unsigned int samples, uint8_t channels, unsigned int sample_rate, void *userdata)
*
* Note that total size of pcm in bytes is equal to (samples * channels * sizeof(int16_t)).
*/ */
int toxav_join_av_groupchat(Tox *tox, int32_t friendnumber, const uint8_t *data, uint16_t length, int toxav_join_av_groupchat(Tox *tox, int32_t friendnumber, const uint8_t *data, uint16_t length,
void (*audio_callback)(Messenger *, int, int, const int16_t *, unsigned int, uint8_t, unsigned int, void *), void (*audio_callback)(Messenger *, int, int, const int16_t *, unsigned int, uint8_t, unsigned int, void *),
@ -1188,6 +1192,14 @@ int toxav_join_av_groupchat(Tox *tox, int32_t friendnumber, const uint8_t *data,
* *
* return 0 on success. * return 0 on success.
* return -1 on failure. * return -1 on failure.
*
* Note that total size of pcm in bytes is equal to (samples * channels * sizeof(int16_t)).
*
* Valid number of samples are ((sample rate) * (audio length (Valid ones are: 2.5, 5, 10, 20, 40 or 60 ms)) / 1000)
* Valid number of channels are 1 or 2.
* Valid sample rates are 8000, 12000, 16000, 24000, or 48000.
*
* Recommended values are: samples = 960, channels = 1, sample_rate = 48000
*/ */
int toxav_group_send_audio(Tox *tox, int groupnumber, const int16_t *pcm, unsigned int samples, uint8_t channels, int toxav_group_send_audio(Tox *tox, int groupnumber, const int16_t *pcm, unsigned int samples, uint8_t channels,
unsigned int sample_rate) unsigned int sample_rate)

View File

@ -390,6 +390,8 @@ int toxav_has_activity ( ToxAv *av, int32_t call_index, int16_t *PCM, uint16_t f
* *
* Audio data callback format: * Audio data callback format:
* audio_callback(Tox *tox, int groupnumber, int peernumber, const int16_t *pcm, unsigned int samples, uint8_t channels, unsigned int sample_rate, void *userdata) * audio_callback(Tox *tox, int groupnumber, int peernumber, const int16_t *pcm, unsigned int samples, uint8_t channels, unsigned int sample_rate, void *userdata)
*
* Note that total size of pcm in bytes is equal to (samples * channels * sizeof(int16_t)).
*/ */
int toxav_add_av_groupchat(Tox *tox, void (*audio_callback)(Tox *, int, int, const int16_t *, unsigned int, uint8_t, int toxav_add_av_groupchat(Tox *tox, void (*audio_callback)(Tox *, int, int, const int16_t *, unsigned int, uint8_t,
unsigned int, void *), void *userdata); unsigned int, void *), void *userdata);
@ -401,6 +403,8 @@ int toxav_add_av_groupchat(Tox *tox, void (*audio_callback)(Tox *, int, int, con
* *
* Audio data callback format (same as the one for toxav_add_av_groupchat()): * Audio data callback format (same as the one for toxav_add_av_groupchat()):
* audio_callback(Tox *tox, int groupnumber, int peernumber, const int16_t *pcm, unsigned int samples, uint8_t channels, unsigned int sample_rate, void *userdata) * audio_callback(Tox *tox, int groupnumber, int peernumber, const int16_t *pcm, unsigned int samples, uint8_t channels, unsigned int sample_rate, void *userdata)
*
* Note that total size of pcm in bytes is equal to (samples * channels * sizeof(int16_t)).
*/ */
int toxav_join_av_groupchat(Tox *tox, int32_t friendnumber, const uint8_t *data, uint16_t length, int toxav_join_av_groupchat(Tox *tox, int32_t friendnumber, const uint8_t *data, uint16_t length,
void (*audio_callback)(Tox *, int, int, const int16_t *, unsigned int, uint8_t, unsigned int, void *), void *userdata); void (*audio_callback)(Tox *, int, int, const int16_t *, unsigned int, uint8_t, unsigned int, void *), void *userdata);
@ -409,6 +413,16 @@ int toxav_join_av_groupchat(Tox *tox, int32_t friendnumber, const uint8_t *data,
* *
* return 0 on success. * return 0 on success.
* return -1 on failure. * return -1 on failure.
*
* Note that total size of pcm in bytes is equal to (samples * channels * sizeof(int16_t)).
*
* Valid number of samples are ((sample rate) * (audio length (Valid ones are: 2.5, 5, 10, 20, 40 or 60 ms)) / 1000)
* Valid number of channels are 1 or 2.
* Valid sample rates are 8000, 12000, 16000, 24000, or 48000.
*
* Recommended values are: samples = 960, channels = 1, sample_rate = 48000
*
* TODO: currently the only supported sample rate is 48000.
*/ */
int toxav_group_send_audio(Tox *tox, int groupnumber, const int16_t *pcm, unsigned int samples, uint8_t channels, int toxav_group_send_audio(Tox *tox, int groupnumber, const int16_t *pcm, unsigned int samples, uint8_t channels,
unsigned int sample_rate); unsigned int sample_rate);