void DecoderIrregular::setChannelPosition(unsigned int index, double azimuth) { long number_of_virutal_channels; double current_distance, minimum_distance; Planewaves::setChannelPosition(index, azimuth); // Sort the channels azimuth memcpy(m_channels_azimuth_sorted, m_channels_azimuth, m_number_of_channels * sizeof(double)); std::sort(m_channels_azimuth_sorted, m_channels_azimuth_sorted+m_number_of_channels); // Get the minimum distance between the channels minimum_distance = HOA_2PI + 1; current_distance = distance_radian(m_channels_azimuth_sorted[0], m_channels_azimuth_sorted[m_number_of_channels-1]); if(current_distance < minimum_distance) minimum_distance = current_distance; for(unsigned int i = 1; i < m_number_of_channels; i++) { current_distance = distance_radian(m_channels_azimuth_sorted[i], m_channels_azimuth_sorted[i-1]); if(current_distance < minimum_distance) minimum_distance = current_distance; } // Get the optimal number of virtual channels // Always prefer the number of harmonics + 2 number_of_virutal_channels = (HOA_2PI / minimum_distance); if(number_of_virutal_channels < m_number_of_harmonics + 2) { number_of_virutal_channels = m_number_of_harmonics + 2; } for(unsigned int i = 0; i < m_number_of_channels * m_number_of_harmonics; i++) { m_decoder_matrix_sorted[i] = 0; m_decoder_matrix[i] = 0; } // Compute the decoding matrix for sorted channels for(unsigned int i = 0; i < number_of_virutal_channels; i++) { long channel_index1 = 0, channel_index2 = 0; double factor_index1 = 0, factor_index2 = 0; // Get the pair of real channels corresponding to the virtual channel double angle = (double)i / (double)number_of_virutal_channels * HOA_2PI; for(unsigned int j = 0; j < m_number_of_channels; j++) { if(j < m_number_of_channels-1 && angle >= m_channels_azimuth_sorted[j] && angle <= m_channels_azimuth_sorted[j+1]) { channel_index1 = j; channel_index2 = j+1; // Get the factor for the pair of real channels double distance_index1 = angle - m_channels_azimuth_sorted[j]; double distance_index2 = m_channels_azimuth_sorted[j+1] - angle; double distance_ratio = distance_index1 + distance_index2; factor_index1 = cos(distance_index1 / (distance_ratio) * HOA_PI); factor_index2 = cos(distance_index2 / (distance_ratio) * HOA_PI); break; } else { channel_index1 = j; channel_index2 = 0; // Get the factor for the pair of real channels double distance_index1 = angle - m_channels_azimuth_sorted[j]; double distance_index2 = (m_channels_azimuth_sorted[0] + HOA_2PI) - angle; double distance_ratio = distance_index1 + distance_index2; factor_index1 = cos(distance_index1 / (distance_ratio) * HOA_PI); factor_index2 = cos(distance_index2 / (distance_ratio) * HOA_PI); break; } } // Get the harmonics coefficients for virtual channel m_encoder->setAzimuth(angle); m_encoder->process(1., m_harmonics_vector); m_decoder_matrix_sorted[channel_index1 * m_number_of_harmonics] += (0.5 / (double)(m_order + 1.)) * factor_index1; m_decoder_matrix_sorted[channel_index2 * m_number_of_harmonics] += (0.5 / (double)(m_order + 1.)) * factor_index2; for(unsigned int j = 1; j < m_number_of_harmonics; j++) { m_decoder_matrix_sorted[channel_index1 * m_number_of_harmonics + j] += (m_harmonics_vector[j] / (double)(m_order + 1.)) * factor_index1; m_decoder_matrix_sorted[channel_index2 * m_number_of_harmonics + j] += (m_harmonics_vector[j] / (double)(m_order + 1.)) * factor_index2; } } // Copy the decoding matrix for sorted channels to the decoding matrix for unsorted channels for(unsigned int i = 0; i < m_number_of_channels; i++) { for(unsigned int j = 0; j < m_number_of_channels; j++) { if(m_channels_azimuth[i] == m_channels_azimuth_sorted[j]) { for(unsigned int k = 0; k < m_number_of_harmonics; k++) { m_decoder_matrix_float[i * m_number_of_harmonics + k] = m_decoder_matrix[i * m_number_of_harmonics + k] = m_decoder_matrix_sorted[j * m_number_of_harmonics + k]; } } } } }
void DecoderIrregular::setChannelAzimuth(unsigned int index, double azimuth) { double current_distance, minimum_distance; Planewaves::setChannelAzimuth(index, azimuth); // Get the minimum distance between the channels minimum_distance = HOA_2PI + 1; current_distance = distance_radian(m_channels_azimuth[0], m_channels_azimuth[m_number_of_channels-1]); if(current_distance < minimum_distance) minimum_distance = current_distance; for(unsigned int i = 1; i < m_number_of_channels; i++) { current_distance = distance_radian(m_channels_azimuth[i], m_channels_azimuth[i-1]); if(current_distance < minimum_distance) minimum_distance = current_distance; } // Get the optimal number of virtual channels // Always prefer the number of harmonics + 1 if(minimum_distance > 0) m_number_of_virtual_channels = (HOA_2PI / minimum_distance); else m_number_of_virtual_channels = m_number_of_harmonics + 1; if(m_number_of_virtual_channels < m_number_of_harmonics + 1) { m_number_of_virtual_channels = m_number_of_harmonics + 1; } if(m_nearest_channel[0] && m_nearest_channel[1]) { delete [] m_nearest_channel[0]; delete [] m_nearest_channel[1]; } m_nearest_channel[0] = new unsigned int[m_number_of_virtual_channels]; m_nearest_channel[1] = new unsigned int[m_number_of_virtual_channels]; for(unsigned int i = 0; i < m_number_of_channels * m_number_of_harmonics; i++) { m_decoder_matrix[i] = 0.; m_decoder_matrix_float[i] = 0.; } if(m_number_of_channels == 1) { for(unsigned int i = 0; i < m_number_of_virtual_channels; i++) { double angle = (double)i / (double)m_number_of_virtual_channels * HOA_2PI; m_encoder->setAzimuth(angle + m_offset); m_encoder->process(1., m_harmonics_vector); m_decoder_matrix[0] += (0.5 / (double)(m_order + 1.)); for(unsigned int j = 1; j < m_number_of_harmonics; j++) { m_decoder_matrix[j] += (m_harmonics_vector[j] / (double)(m_order + 1.)); } } for(unsigned int i = 0; i < m_number_of_harmonics; i++) { m_decoder_matrix_float[i] = m_decoder_matrix[i]; } } else if(m_number_of_channels == 2) { for(unsigned int i = 0; i < m_number_of_virtual_channels; i++) { double factor_index1 = 0, factor_index2 = 0; double angle = (double)i / (double)m_number_of_virtual_channels * HOA_2PI; m_encoder->setAzimuth(angle + m_offset); m_encoder->process(1., m_harmonics_vector); m_decoder_matrix[0] += (0.5 / (double)(m_order + 1.)); m_decoder_matrix[m_number_of_harmonics] += (0.5 / (double)(m_order + 1.)); factor_index1 = fabs(cos(distance_radian(angle, m_channels_azimuth[0]) / HOA_PI * HOA_PI2)); factor_index2 = fabs(cos(distance_radian(angle, m_channels_azimuth[1]) / HOA_PI * HOA_PI2)); for(unsigned int j = 1; j < m_number_of_harmonics; j++) { m_decoder_matrix[j] += (m_harmonics_vector[j] / (double)(m_order + 1.)) * factor_index1; m_decoder_matrix[m_number_of_harmonics + j] += (m_harmonics_vector[j] / (double)(m_order + 1.)) * factor_index2; } } for(unsigned int i = 0; i < m_number_of_channels * m_number_of_harmonics; i++) { m_decoder_matrix_float[i] = m_decoder_matrix[i]; } } else { // Get the nearest channels for(unsigned int i = 0; i < m_number_of_virtual_channels; i++) { long channel_index1 = 0, channel_index2 = 0; double distance1 = HOA_2PI, distance2 = HOA_2PI; double angle = (double)i / (double)m_number_of_virtual_channels * HOA_2PI; double factor_index1 = 0, factor_index2 = 0; for(unsigned int j = 0; j < m_number_of_channels; j++) { if(radianClosestDistance(m_channels_azimuth[j], angle) < distance1) { distance1 = radianClosestDistance(m_channels_azimuth[j], angle); channel_index1 = j; } } for(unsigned int j = 0; j < m_number_of_channels; j++) { if(radianClosestDistance(m_channels_azimuth[j], angle) < distance2 && j != channel_index1) { distance2 = radianClosestDistance(m_channels_azimuth[j], angle); channel_index2 = j; } } if(fabs(distance1 - distance2) < HOA_PI / (double)m_number_of_virtual_channels) { double angle1 = m_channels_azimuth[channel_index1], angle2 = m_channels_azimuth[channel_index2]; double distance_index1 = radianClosestDistance(angle, angle1); double distance_index2 = radianClosestDistance(angle, angle2); double distance_ratio = distance_index1 + distance_index2; factor_index1 = cos(distance_index1 / (distance_ratio) * HOA_PI2); factor_index2 = cos(distance_index2 / (distance_ratio) * HOA_PI2); } else { factor_index1 = 1; factor_index2 = 0; } // Get the harmonics coefficients for the virtual channel m_encoder->setAzimuth(angle + m_offset); m_encoder->process(1., m_harmonics_vector); m_decoder_matrix[channel_index1 * m_number_of_harmonics] += (0.5 / (double)(m_order + 1.)) * factor_index1; m_decoder_matrix[channel_index2 * m_number_of_harmonics] += (0.5 / (double)(m_order + 1.)) * factor_index2; for(unsigned int j = 1; j < m_number_of_harmonics; j++) { m_decoder_matrix[channel_index1 * m_number_of_harmonics + j] += (m_harmonics_vector[j] / (double)(m_order + 1.)) * factor_index1; m_decoder_matrix[channel_index2 * m_number_of_harmonics + j] += (m_harmonics_vector[j] / (double)(m_order + 1.)) * factor_index2; } } for(unsigned int i = 0; i < m_number_of_channels * m_number_of_harmonics; i++) { m_decoder_matrix_float[i] = m_decoder_matrix[i]; } } }