Unverified Commit 40e3c703 authored by Andrew Allen's avatar Andrew Allen Committed by Jean-Marc Valin

Support for Ambisonics.

Signed-off-by: Jean-Marc Valin's avatarJean-Marc Valin <jmvalin@jmvalin.ca>
parent a1b213a3
......@@ -46,7 +46,8 @@
- if (mapping != 0)
- N = total number of streams (8 bits)
- M = number of paired streams (8 bits)
- C times channel origin
- if (mapping != a projection family)
- C times channel origin
- if (C<2*M)
- stream = byte/2
- if (byte&0x1 == 0)
......@@ -55,6 +56,8 @@
- right
- else
- stream = byte-M
- else
- D demixing matrix (C*(N+M)*16 bits)
*/
typedef struct {
......@@ -101,7 +104,49 @@ static int write_chars(Packet *p, const unsigned char *str, int nb_chars)
return 1;
}
int _ope_opus_header_to_packet(const OpusHeader *h, unsigned char *packet, int len)
static int write_matrix_chars(Packet *p, const OpusGenericEncoder *st)
{
#ifdef OPUS_HAVE_OPUS_PROJECTION_H
opus_int32 size;
int ret;
ret=opeint_encoder_ctl(st, OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE(&size));
if (ret != OPUS_OK) return 0;
if (size>p->maxlen-p->pos) return 0;
ret=opeint_encoder_ctl(st, OPUS_PROJECTION_GET_DEMIXING_MATRIX(&p->data[p->pos], size));
if (ret != OPUS_OK) return 0;
p->pos += size;
return 1;
#else
(void)p;
(void)st;
return 0;
#endif
}
int _ope_opus_header_get_size(const OpusHeader *h)
{
int len=0;
if (opeint_use_projection(h->channel_mapping))
{
/* 19 bytes from fixed header,
* 2 bytes for nb_streams & nb_coupled,
* 2 bytes per cell of demixing matrix, where:
* rows=channels, cols=nb_streams+nb_coupled
*/
len=21+(h->channels*(h->nb_streams+h->nb_coupled)*2);
}
else
{
/* 19 bytes from fixed header,
* 2 bytes for nb_streams & nb_coupled,
* 1 byte per channel
*/
len=21+h->channels;
}
return len;
}
int _ope_opus_header_to_packet(const OpusHeader *h, unsigned char *packet, int len, const OpusGenericEncoder *st)
{
int i;
Packet p;
......@@ -128,8 +173,24 @@ int _ope_opus_header_to_packet(const OpusHeader *h, unsigned char *packet, int l
if (!write_uint32(&p, h->input_sample_rate))
return 0;
if (!write_uint16(&p, h->gain))
if (opeint_use_projection(h->channel_mapping))
{
#ifdef OPUS_HAVE_OPUS_PROJECTION_H
opus_int32 matrix_gain;
int ret;
ret=opeint_encoder_ctl(st, OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN(&matrix_gain));
if (ret != OPUS_OK) return 0;
if (!write_uint16(&p, h->gain + matrix_gain))
return 0;
#else
return 0;
#endif
}
else
{
if (!write_uint16(&p, h->gain))
return 0;
}
ch = h->channel_mapping;
if (!write_chars(&p, &ch, 1))
......@@ -146,10 +207,18 @@ int _ope_opus_header_to_packet(const OpusHeader *h, unsigned char *packet, int l
return 0;
/* Multi-stream support */
for (i=0;i<h->channels;i++)
if (opeint_use_projection(h->channel_mapping))
{
if (!write_matrix_chars(&p, st))
return 0;
}
else
{
if (!write_chars(&p, &h->stream_map[i], 1))
return 0;
for (i=0;i<h->channels;i++)
{
if (!write_chars(&p, &h->stream_map[i], 1))
return 0;
}
}
}
......
......@@ -31,6 +31,45 @@
#include <stdlib.h>
#include <opus.h>
#include <opus_multistream.h>
#ifdef OPUS_HAVE_OPUS_PROJECTION_H
#include <opus_projection.h>
#endif
typedef struct OpusGenericEncoder OpusGenericEncoder;
struct OpusGenericEncoder {
OpusMSEncoder *ms;
#ifdef OPUS_HAVE_OPUS_PROJECTION_H
OpusProjectionEncoder *pr;
#endif
};
int opeint_use_projection(int channel_mapping);
int opeint_encoder_surround_init(OpusGenericEncoder *st, int Fs, int channels, int channel_mapping, int *nb_streams, int *nb_coupled, unsigned char *stream_map, int application);
void opeint_encoder_cleanup(OpusGenericEncoder *st);
int opeint_encoder_init(OpusGenericEncoder *st, opus_int32 Fs, int channels, int streams, int coupled_streams, const unsigned char *mapping, int application);
int opeint_encode_float(OpusGenericEncoder *st, const float *pcm, int frame_size, unsigned char *data, opus_int32 max_data_bytes);
#ifdef OPUS_HAVE_OPUS_PROJECTION_H
# define opeint_encoder_ctl(st, request) \
((st)->pr!=NULL ? \
opus_projection_encoder_ctl((st)->pr, request) : \
opus_multistream_encoder_ctl((st)->ms, request))
# define opeint_encoder_ctl2(st, request, value) \
((st)->pr!=NULL ? \
opus_projection_encoder_ctl((st)->pr, request, value) : \
opus_multistream_encoder_ctl((st)->ms, request, value))
#else
# define opeint_encoder_ctl(st, request) \
opus_multistream_encoder_ctl((st)->ms, request)
# define opeint_encoder_ctl2(st, request, value) \
opus_multistream_encoder_ctl((st)->ms, request, value)
#endif
typedef struct {
int version;
int channels; /* Number of channels: 1..255 */
......@@ -44,7 +83,9 @@ typedef struct {
unsigned char stream_map[255];
} OpusHeader;
int _ope_opus_header_to_packet(const OpusHeader *h, unsigned char *packet, int len);
int _ope_opus_header_get_size(const OpusHeader *h);
int _ope_opus_header_to_packet(const OpusHeader *h, unsigned char *packet, int len, const OpusGenericEncoder *st);
void _ope_comment_init(char **comments, int* length, const char *vendor_string);
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment