diff --git a/spa/include/spa/param/audio/raw.h b/spa/include/spa/param/audio/raw.h index 60f19e1fd..47425ab5f 100644 --- a/spa/include/spa/param/audio/raw.h +++ b/spa/include/spa/param/audio/raw.h @@ -152,41 +152,42 @@ enum spa_audio_channel { SPA_AUDIO_CHANNEL_MONO, /**< mono stream */ - SPA_AUDIO_CHANNEL_FL, /**< front left */ - SPA_AUDIO_CHANNEL_FR, /**< front right */ - SPA_AUDIO_CHANNEL_FC, /**< front center */ - SPA_AUDIO_CHANNEL_LFE, /**< LFE */ - SPA_AUDIO_CHANNEL_SL, /**< side left */ - SPA_AUDIO_CHANNEL_SR, /**< side right */ - SPA_AUDIO_CHANNEL_FLC, /**< front left center */ - SPA_AUDIO_CHANNEL_FRC, /**< front right center */ - SPA_AUDIO_CHANNEL_RC, /**< rear center */ - SPA_AUDIO_CHANNEL_RL, /**< rear left */ - SPA_AUDIO_CHANNEL_RR, /**< rear right */ - SPA_AUDIO_CHANNEL_TC, /**< top center */ - SPA_AUDIO_CHANNEL_TFL, /**< top front left */ - SPA_AUDIO_CHANNEL_TFC, /**< top front center */ - SPA_AUDIO_CHANNEL_TFR, /**< top front right */ - SPA_AUDIO_CHANNEL_TRL, /**< top rear left */ - SPA_AUDIO_CHANNEL_TRC, /**< top rear center */ - SPA_AUDIO_CHANNEL_TRR, /**< top rear right */ - SPA_AUDIO_CHANNEL_RLC, /**< rear left center */ - SPA_AUDIO_CHANNEL_RRC, /**< rear right center */ - SPA_AUDIO_CHANNEL_FLW, /**< front left wide */ - SPA_AUDIO_CHANNEL_FRW, /**< front right wide */ - SPA_AUDIO_CHANNEL_LFE2, /**< LFE 2 */ - SPA_AUDIO_CHANNEL_FLH, /**< front left high */ - SPA_AUDIO_CHANNEL_FCH, /**< front center high */ - SPA_AUDIO_CHANNEL_FRH, /**< front right high */ - SPA_AUDIO_CHANNEL_TFLC, /**< top front left center */ - SPA_AUDIO_CHANNEL_TFRC, /**< top front right center */ - SPA_AUDIO_CHANNEL_TSL, /**< top side left */ - SPA_AUDIO_CHANNEL_TSR, /**< top side right */ - SPA_AUDIO_CHANNEL_LLFE, /**< left LFE */ - SPA_AUDIO_CHANNEL_RLFE, /**< right LFE */ - SPA_AUDIO_CHANNEL_BC, /**< bottom center */ - SPA_AUDIO_CHANNEL_BLC, /**< bottom left center */ - SPA_AUDIO_CHANNEL_BRC, /**< bottom right center */ + /** Azimuth Elevation */ + SPA_AUDIO_CHANNEL_FL, /**< front left 30 0 */ + SPA_AUDIO_CHANNEL_FR, /**< front right -30 0 */ + SPA_AUDIO_CHANNEL_FC, /**< front center 0 0 */ + SPA_AUDIO_CHANNEL_LFE, /**< LFE 0 -30 */ + SPA_AUDIO_CHANNEL_SL, /**< side left 90 0 */ + SPA_AUDIO_CHANNEL_SR, /**< side right -90 0 */ + SPA_AUDIO_CHANNEL_FLC, /**< front left center 22.5 0 */ + SPA_AUDIO_CHANNEL_FRC, /**< front right center -22.5 0 */ + SPA_AUDIO_CHANNEL_RC, /**< rear center 180 0 */ + SPA_AUDIO_CHANNEL_RL, /**< rear left 110 0 */ + SPA_AUDIO_CHANNEL_RR, /**< rear right -110 0 */ + SPA_AUDIO_CHANNEL_TC, /**< top center 0 90 */ + SPA_AUDIO_CHANNEL_TFL, /**< top front left 30 30 */ + SPA_AUDIO_CHANNEL_TFC, /**< top front center 0 30 */ + SPA_AUDIO_CHANNEL_TFR, /**< top front right -30 30 */ + SPA_AUDIO_CHANNEL_TRL, /**< top rear left 110 30 */ + SPA_AUDIO_CHANNEL_TRC, /**< top rear center 180 30 */ + SPA_AUDIO_CHANNEL_TRR, /**< top rear right -110 30 */ + SPA_AUDIO_CHANNEL_RLC, /**< rear left center 135 0 */ + SPA_AUDIO_CHANNEL_RRC, /**< rear right center -135 0 */ + SPA_AUDIO_CHANNEL_FLW, /**< front left wide 60 0 */ + SPA_AUDIO_CHANNEL_FRW, /**< front right wide -60 0 */ + SPA_AUDIO_CHANNEL_LFE2, /**< LFE 2 0 -30 */ + SPA_AUDIO_CHANNEL_FLH, /**< front left high 22.5 30 */ + SPA_AUDIO_CHANNEL_FCH, /**< front center high 0 30 */ + SPA_AUDIO_CHANNEL_FRH, /**< front right high -22.5 30 */ + SPA_AUDIO_CHANNEL_TFLC, /**< top front left center 45 30 */ + SPA_AUDIO_CHANNEL_TFRC, /**< top front right center -45 30 */ + SPA_AUDIO_CHANNEL_TSL, /**< top side left 90 0 */ + SPA_AUDIO_CHANNEL_TSR, /**< top side right -90 0 */ + SPA_AUDIO_CHANNEL_LLFE, /**< left LFE 45 -30 */ + SPA_AUDIO_CHANNEL_RLFE, /**< right LFE -45 -30 */ + SPA_AUDIO_CHANNEL_BC, /**< bottom center 0 -30 */ + SPA_AUDIO_CHANNEL_BLC, /**< bottom left center 45 -30 */ + SPA_AUDIO_CHANNEL_BRC, /**< bottom right center -45 -30 */ SPA_AUDIO_CHANNEL_START_Aux = 0x1000, /**< aux channels */ SPA_AUDIO_CHANNEL_AUX0 = SPA_AUDIO_CHANNEL_START_Aux, diff --git a/spa/plugins/audioconvert/channelmix-ops.c b/spa/plugins/audioconvert/channelmix-ops.c index d774112bc..71158771b 100644 --- a/spa/plugins/audioconvert/channelmix-ops.c +++ b/spa/plugins/audioconvert/channelmix-ops.c @@ -117,6 +117,7 @@ static const struct channelmix_info *find_channelmix_info(uint32_t src_chan, uin #define SQRT3_2 1.224744871f /* sqrt(3/2) */ #define SQRT1_2 0.707106781f #define SQRT2 1.414213562f +#define HALF 0.5f #define MATRIX_NORMAL 0 #define MATRIX_DOLBY 1 @@ -127,7 +128,11 @@ static const struct channelmix_info *find_channelmix_info(uint32_t src_chan, uin #define _MASK(ch) (1ULL << _CH(ch)) #define FRONT (_MASK(FC)) #define STEREO (_MASK(FL)|_MASK(FR)) +#define TSTEREO (_MASK(TFL)|_MASK(TFR)) +#define TCSTEREO (_MASK(TFLC)|_MASK(TFRC)) #define REAR (_MASK(RL)|_MASK(RR)) +#define TREAR (_MASK(TRL)|_MASK(TRR)) +#define CREAR (_MASK(RLC)|_MASK(RRC)) #define SIDE (_MASK(SL)|_MASK(SR)) static uint32_t mask_to_ch(struct channelmix *mix, uint64_t mask) @@ -403,7 +408,7 @@ static int make_matrix(struct channelmix *mix) } normalize = true; } else { - spa_log_warn(mix->log, "can't assign RL"); + spa_log_warn(mix->log, "can't assign RL+RR"); } } @@ -498,6 +503,93 @@ static int make_matrix(struct channelmix *mix) spa_log_warn(mix->log, "can't assign LFE"); } } + if (unassigned & TSTEREO){ + if (dst_mask & STEREO) { + spa_log_info(mix->log, "assign TSTEREO to FL+FR (%f)", HALF); + _MATRIX(FL,TFL) += HALF; + _MATRIX(FR,TFR) += HALF; + } else if (dst_mask & _MASK(MONO)){ + spa_log_info(mix->log, "assign TSTEREO to MONO (%f)", 1.0f); + for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++) { + matrix[i][_CH(TFL)]= 1.0f; + matrix[i][_CH(TFR)]= 1.0f; + } + normalize = true; + } else { + spa_log_warn(mix->log, "can't assign TSTEREO"); + } + } + if (unassigned & TCSTEREO){ + if (dst_mask & STEREO) { + spa_log_info(mix->log, "assign TCSTEREO to FL+FR (%f)", HALF); + _MATRIX(FL,TFLC) += HALF; + _MATRIX(FR,TFRC) += HALF; + } else if (dst_mask & _MASK(MONO)){ + spa_log_info(mix->log, "assign TCSTEREO to MONO (%f)", 1.0f); + for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++) { + matrix[i][_CH(TFLC)]= 1.0f; + matrix[i][_CH(TFRC)]= 1.0f; + } + normalize = true; + } else { + spa_log_warn(mix->log, "can't assign TCSTEREO"); + } + } + if (unassigned & TREAR){ + if (dst_mask & REAR) { + if (src_mask & _MASK(RL)) { + spa_log_info(mix->log, "assign TREAR to RL+RR (%f)", HALF); + _MATRIX(RL,TRL) += HALF; + _MATRIX(RR,TRR) += HALF; + } else { + spa_log_info(mix->log, "assign TREAR to RL+RR (%f)", 1.0f); + _MATRIX(RL,TRL) += 1.0f; + _MATRIX(RR,TRR) += 1.0f; + } + keep &= ~REAR; + } else if (dst_mask & STEREO) { + spa_log_info(mix->log, "assign TREAR to FL+FR (%f)", HALF); + _MATRIX(FL,TRL) += HALF; + _MATRIX(FR,TRR) += HALF; + } else if (dst_mask & _MASK(MONO)){ + spa_log_info(mix->log, "assign TREAR to MONO (%f)", 1.0f); + for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++) { + matrix[i][_CH(TRL)]= 1.0f; + matrix[i][_CH(TRR)]= 1.0f; + } + normalize = true; + } else { + spa_log_warn(mix->log, "can't assign TREAR"); + } + } + if (unassigned & CREAR){ + if (dst_mask & REAR) { + if (src_mask & _MASK(RL)) { + spa_log_info(mix->log, "assign CREAR to RL+RR (%f)", SQRT1_2); + _MATRIX(RL,RLC) += SQRT1_2; + _MATRIX(RR,RRC) += SQRT1_2; + } else { + spa_log_info(mix->log, "assign CREAR to RL+RR (%f)", 1.0f); + _MATRIX(RL,RLC) += 1.0f; + _MATRIX(RR,RRC) += 1.0f; + } + keep &= ~REAR; + } else if (dst_mask & STEREO) { + spa_log_info(mix->log, "assign CREAR to FL+FR (%f)", + SQRT1_2); + _MATRIX(FL,RLC) += SQRT1_2; + _MATRIX(FR,RRC) += SQRT1_2; + } else if (dst_mask & _MASK(MONO)){ + spa_log_info(mix->log, "assign CREAR to MONO (%f)", 1.0f); + for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++) { + matrix[i][_CH(RLC)]= 1.0f; + matrix[i][_CH(RRC)]= 1.0f; + } + normalize = true; + } else { + spa_log_warn(mix->log, "can't assign CREAR"); + } + } unassigned = dst_mask & ~src_mask & keep;