Пример #1
0
        /// <summary>
        /// Construct with configuration and output stream writer
        /// </summary>
        /// <param name="config"></param>
        public Callback(AnalyserConfig config)
        {
            this.config = config;

            // sps is assumed to be even
            var sps = config.SamplesPerSlot;

            channelData = new Channel[Analyser.CHANNELS];
            for (var c = 0; c < Analyser.CHANNELS; c++)
            {
                channelData[c] = new Channel(config);
            }

            window0 = new double[sps];
            window1 = new double[sps];
            window2 = new double[sps];

            // Build a triangular window across 3 slots
            var half = sps * 3 >> 1;
            var end  = (sps << 1) - 1;
            var step = 1.0 / (half - 1);

            for (var i = 0; i < sps; i++)
            {
                window0[i] = window2[sps - 1 - i] = i * step;
            }

            for (var i = sps; i < half; i++)
            {
                window1[i - sps] = window1[end - i] = i * step;
            }
        }
Пример #2
0
        /// <summary>
        /// Generate an audio fingerprint for each selected input audio channel in the buffer
        /// </summary>
        /// <param name="buffer"></param>
        /// <returns></returns>
        internal unsafe ulong[] GetAudioFingerprints(IntPtr buffer, AnalyserConfig config)
        {
            var signatures = new ulong[Analyser.CHANNELS];

            // window support
            var support = config.SamplesPerSlot * 3;

            for (var channel = 0; channel < Analyser.CHANNELS; channel++)
            {
                var signature     = 0UL;
                var signalPresent = false;
                var cd            = channelData[channel];

                // Initialise sptr to the first sample for the channel
                var sptr = (short *)(buffer) + channel;
                var bit  = 1UL << config.SlotsPerFrame;
                for (var slot = 0; slot < config.SlotsPerFrame; slot++)
                {
                    // Sum of squares of windowed samples
                    var ssqr = 0.0;
                    for (var i = 0; i < config.SamplesPerSlot; i++)
                    {
                        var sample = *sptr;
                        // Step to the same channel in the next sample
                        sptr += Analyser.CHANNELS;
                        var fsample = cd.Filter.Filter(sample);
                        cd.Slot2[i] = fsample * fsample;

                        ssqr += window0[i] * cd.Slot0[i] + window1[i] * cd.Slot1[i] + window2[i] * cd.Slot2[i];
                    }
                    signalPresent = signalPresent || (ssqr > 0);

                    // Convert to logarithmic RMS
                    // The log scaling ensures that we are working with perceived loudness
                    var rms = signalPresent ? Math.Log10(ssqr / support) : 0.0;

                    // Rotate the slot buffers
                    var tmp = cd.Slot0;
                    cd.Slot0 = cd.Slot1;
                    cd.Slot1 = cd.Slot2;
                    cd.Slot2 = tmp;

                    bit >>= 1;
                    var rmsa = cd.RmsBuffer.Average();
                    if (rms > rmsa)
                    {
                        signature |= bit;
                    }

                    Buffer.BlockCopy(cd.RmsBuffer, sizeof(double), cd.RmsBuffer, 0, (config.FirLength - 1) * sizeof(double));
                    cd.RmsBuffer[config.FirLength - 1] = rms;
                }
                // MSB is a signal present flag
                if (signalPresent)
                {
                    signature |= 0x8000000000000000UL;
                }

                signatures[channel] = signature;
            }
            return(signatures);
        }
Пример #3
0
 public Analyser(AnalyserConfig config)
 {
     this.config = config;
 }