/* sets the input format, and returns the requested channel layout */ enum PCMChannels *CPCMRemap::SetInputFormat(unsigned int channels, enum PCMChannels *channelMap, unsigned int sampleSize, unsigned int sampleRate) { m_inChannels = channels; m_inSampleSize = sampleSize; m_sampleRate = (float)sampleRate; m_inSet = channelMap != NULL; if (channelMap) memcpy(m_inMap, channelMap, sizeof(enum PCMChannels) * channels); /* fix me later */ assert(sampleSize == 2); /* get the audio layout, and count the channels in it */ if (!m_bAudio2) m_channelLayout = (enum PCMLayout)g_guiSettings.GetInt("audiooutput.channellayout"); else m_channelLayout = (enum PCMLayout)g_guiSettings.GetInt("audiooutput2.channellayout"); if (m_channelLayout >= PCM_MAX_LAYOUT) m_channelLayout = PCM_LAYOUT_2_0; //spdif only has 2 pcm channels, so don't try to use more if (g_guiSettings.GetInt("audiooutput.mode") == AUDIO_IEC958) { CLog::Log(LOGINFO, "CPCMRemap: Configured speaker layout: %s (iec958)\n", PCMLayoutStr(m_channelLayout).c_str()); m_channelLayout = PCM_LAYOUT_2_0; } else CLog::Log(LOGINFO, "CPCMRemap: Configured speaker layout: %s\n", PCMLayoutStr(m_channelLayout).c_str()); DumpMap("I", channels, channelMap); BuildMap(); /* now remove the empty channels from PCMLayoutMap; * we don't perform upmixing so we want the minimum amount of those */ if (channelMap) { if (!m_outSet) ResolveChannels(); /* Do basic channel resolving to find out the empty channels; * If m_outSet == true, this was done already by BuildMap() above */ int i = 0; for (enum PCMChannels *chan = PCMLayoutMap[m_channelLayout]; *chan != PCM_INVALID; ++chan) if (m_lookupMap[*chan][0].channel != PCM_INVALID) { /* something is mapped here, so add the channel */ m_layoutMap[i++] = *chan; } m_layoutMap[i] = PCM_INVALID; } else memcpy(m_layoutMap, PCMLayoutMap[m_channelLayout], sizeof(PCMLayoutMap[m_channelLayout])); m_attenuation = 1.0; m_attenuationInc = 1.0; m_holdCounter = 0; return m_layoutMap; }
void KickPrefetchChannels(const struct NaClApp *nap) { int i; /* quietly return if no name service specified */ if(!NameServiceSet()) return; assert(nap != NULL); assert(nap->system_manifest != NULL); /* exchange channel information with the name server */ ResolveChannels(nap, binds, connects); /* make connections */ for(i = 0; i < nap->system_manifest->channels_count; ++i) { int result; struct ChannelDesc *channel = &nap->system_manifest->channels[i]; struct ChannelConnection *record; assert(channel != NULL); /* skip all channels except the network "connect" ones */ if(channel->source != ChannelTCP) continue; /* get the channel connection information */ record = GetChannelConnectionInfo(channel); assert(record != NULL); /* only the "connect" channels need to be processed */ if(record->mark != CONNECT_MARK) continue; /* bind or connect the channel and look at result */ result = DoConnect(channel); ZLOGFAIL(result != 0, EFAULT, "cannot connect socket to %s", channel->alias); } /* * temporary fix (the lost 1st messsage) to allow 0mq to complete * the connection procedure. 1 millisecond should be enough * todo(d'b): replace it with the channels readiness check */ usleep(PREPOLL_WAIT); }
/* sets the input format, and returns the requested channel layout */ enum PCMChannels *CPCMRemap::SetInputFormat(unsigned int channels, enum PCMChannels *channelMap, unsigned int sampleSize, unsigned int sampleRate, PCMLayout layout) { m_inChannels = channels; m_inSampleSize = sampleSize; m_sampleRate = sampleRate; m_inSet = channelMap != NULL; if (channelMap) memcpy(m_inMap, channelMap, sizeof(enum PCMChannels) * channels); /* get the audio layout, and count the channels in it */ m_channelLayout = layout; if (m_channelLayout >= PCM_MAX_LAYOUT) m_channelLayout = PCM_LAYOUT_2_0; DumpMap("I", channels, channelMap); BuildMap(); /* now remove the empty channels from PCMLayoutMap; * we don't perform upmixing so we want the minimum amount of those */ if (channelMap) { if (!m_outSet) ResolveChannels(); /* Do basic channel resolving to find out the empty channels; * If m_outSet == true, this was done already by BuildMap() above */ int i = 0; for (enum PCMChannels *chan = PCMLayoutMap[m_channelLayout]; *chan != PCM_INVALID; ++chan) if (m_lookupMap[*chan][0].channel != PCM_INVALID) { /* something is mapped here, so add the channel */ m_layoutMap[i++] = *chan; } m_layoutMap[i] = PCM_INVALID; } else memcpy(m_layoutMap, PCMLayoutMap[m_channelLayout], sizeof(PCMLayoutMap[m_channelLayout])); m_attenuation = 1.0; m_attenuationInc = 1.0; m_holdCounter = 0; return m_layoutMap; }
/* builds a lookup table to convert from the input mapping to the output mapping, this decreases the amount of work per sample to remap it. */ void CPCMRemap::BuildMap() { struct PCMMapInfo *dst; unsigned int out_ch; if (!m_inSet || !m_outSet) return; m_inStride = m_inSampleSize * m_inChannels ; m_outStride = m_inSampleSize * m_outChannels; /* see if we need to normalize the levels */ bool dontnormalize = g_guiSettings.GetBool("audiooutput.dontnormalizelevels"); CLog::Log(LOGDEBUG, "CPCMRemap: Downmix normalization is %s", (dontnormalize ? "disabled" : "enabled")); ResolveChannels(); /* convert the levels into RMS values */ float loudest = 0.0; bool hasLoudest = false; for(out_ch = 0; out_ch < m_outChannels; ++out_ch) { float scale = 0; int count = 0; for(dst = m_lookupMap[m_outMap[out_ch]]; dst->channel != PCM_INVALID; ++dst) { dst->copy = false; dst->level = dst->level / sqrt((float)m_counts[dst->channel]); scale += dst->level; ++count; } /* if there is only 1 channel to mix, and the level is 1.0, then just copy the channel */ dst = m_lookupMap[m_outMap[out_ch]]; if (count == 1 && dst->level > 0.99 && dst->level < 1.01) dst->copy = true; /* normalize the levels if it is turned on */ if (!dontnormalize) for(dst = m_lookupMap[m_outMap[out_ch]]; dst->channel != PCM_INVALID; ++dst) { dst->level /= scale; /* find the loudest output level we have that is not 1-1 */ if (dst->level < 1.0 && loudest < dst->level) { loudest = dst->level; hasLoudest = true; } } } /* adjust the channels that are too loud */ for(out_ch = 0; out_ch < m_outChannels; ++out_ch) { CStdString s = "", f; for(dst = m_lookupMap[m_outMap[out_ch]]; dst->channel != PCM_INVALID; ++dst) { if (hasLoudest && dst->copy) { dst->level = loudest; dst->copy = false; } f.Format("%s(%f%s) ", PCMChannelStr(dst->channel).c_str(), dst->level, dst->copy ? "*" : ""); s += f; } CLog::Log(LOGDEBUG, "CPCMRemap: %s = %s\n", PCMChannelStr(m_outMap[out_ch]).c_str(), s.c_str()); } }