void MatchPipeline::feedConditionedFeatures(const feature_t &c1, const feature_t &c2) { m_c1 = c1; m_c2 = c2; #ifdef DEBUG_MATCH_PIPELINE if (m_lastFrameIn1 == 1) { cerr << "conditioned features 1 -> "; for (int i = 0; i < int(m_c1.size()); ++i) { cerr << m_c1[i] << " "; } cerr << endl; } #endif m_feeder.feed(c1, c2); if (aboveThreshold(c1)) m_lastFrameIn1 = m_frameNo; if (aboveThreshold(c2)) m_lastFrameIn2 = m_frameNo; #ifdef DEBUG_MATCH_PIPELINE cerr << "last frames are " << m_lastFrameIn1 << ", " << m_lastFrameIn2 << endl; #endif ++m_frameNo; }
/* Return number of samples processed in isamp and osamp. */ static int sox_silence_flow(sox_effect_t * effp, const sox_sample_t *ibuf, sox_sample_t *obuf, size_t *isamp, size_t *osamp) { priv_t * silence = (priv_t *) effp->priv; int threshold; size_t i, j; size_t nrOfTicks, /* sometimes wide, sometimes non-wide samples */ nrOfInSamplesRead, nrOfOutSamplesWritten; /* non-wide samples */ nrOfInSamplesRead = 0; nrOfOutSamplesWritten = 0; switch (silence->mode) { case SILENCE_TRIM: /* Reads and discards all input data until it detects a * sample that is above the specified threshold. Turns on * copy mode when detected. * Need to make sure and copy input in groups of "channels" to * prevent getting buffers out of sync. * nrOfTicks counts wide samples here. */ silence_trim: nrOfTicks = min((*isamp-nrOfInSamplesRead), (*osamp-nrOfOutSamplesWritten)) / effp->in_signal.channels; for(i = 0; i < nrOfTicks; i++) { threshold = 0; for (j = 0; j < effp->in_signal.channels; j++) { threshold |= aboveThreshold(effp, compute_rms(effp, ibuf[j]), silence->start_threshold, silence->start_unit); } if (threshold) { /* Add to holdoff buffer */ for (j = 0; j < effp->in_signal.channels; j++) { update_rms(effp, *ibuf); silence->start_holdoff[ silence->start_holdoff_end++] = *ibuf++; nrOfInSamplesRead++; } if (silence->start_holdoff_end >= silence->start_duration) { if (++silence->start_found_periods >= silence->start_periods) { silence->mode = SILENCE_TRIM_FLUSH; goto silence_trim_flush; } /* Trash holdoff buffer since its not * needed. Start looking again. */ silence->start_holdoff_offset = 0; silence->start_holdoff_end = 0; } } else /* !above Threshold */ { silence->start_holdoff_end = 0; for (j = 0; j < effp->in_signal.channels; j++) { update_rms(effp, ibuf[j]); } ibuf += effp->in_signal.channels; nrOfInSamplesRead += effp->in_signal.channels; } } /* for nrOfTicks */ break; case SILENCE_TRIM_FLUSH: /* nrOfTicks counts non-wide samples here. */ silence_trim_flush: nrOfTicks = min((silence->start_holdoff_end - silence->start_holdoff_offset), (*osamp-nrOfOutSamplesWritten)); nrOfTicks -= nrOfTicks % effp->in_signal.channels; for(i = 0; i < nrOfTicks; i++) { *obuf++ = silence->start_holdoff[silence->start_holdoff_offset++]; nrOfOutSamplesWritten++; } /* If fully drained holdoff then switch to copy mode */ if (silence->start_holdoff_offset == silence->start_holdoff_end) { silence->start_holdoff_offset = 0; silence->start_holdoff_end = 0; silence->mode = SILENCE_COPY; goto silence_copy; } break; case SILENCE_COPY: /* Attempts to copy samples into output buffer. * * Case B: * If not looking for silence to terminate copy then * blindly copy data into output buffer. * * Case A: * * Case 1a: * If previous silence was detect then see if input sample is * above threshold. If found then flush out hold off buffer * and copy over to output buffer. * * Case 1b: * If no previous silence detect then see if input sample * is above threshold. If found then copy directly * to output buffer. * * Case 2: * If not above threshold then silence is detect so * store in hold off buffer and do not write to output * buffer. Even though it wasn't put in output * buffer, inform user that input was consumed. * * If hold off buffer is full after this then stop * copying data and discard data in hold off buffer. * * Special leave_silence logic: * * During this mode, go ahead and copy input * samples to output buffer instead of holdoff buffer * Then also short ciruit any flushes that would occur * when non-silence is detect since samples were already * copied. This has the effect of always leaving * holdoff[] amount of silence but deleting any * beyond that amount. * * nrOfTicks counts wide samples here. */ silence_copy: nrOfTicks = min((*isamp-nrOfInSamplesRead), (*osamp-nrOfOutSamplesWritten)) / effp->in_signal.channels; if (silence->stop) { /* Case A */ for(i = 0; i < nrOfTicks; i++) { threshold = 1; for (j = 0; j < effp->in_signal.channels; j++) { threshold &= aboveThreshold(effp, compute_rms(effp, ibuf[j]), silence->stop_threshold, silence->stop_unit); } /* Case 1a * If above threshold, check to see if we where holding * off previously. If so then flush this buffer. * We haven't incremented any pointers yet so nothing * is lost. * * If user wants to leave_silence, then we * were already copying the data and so no * need to flush the old data. Just resume * copying as if we were not holding off. */ if (threshold && silence->stop_holdoff_end && !silence->leave_silence) { silence->mode = SILENCE_COPY_FLUSH; goto silence_copy_flush; } /* Case 1b */ else if (threshold) { /* Not holding off so copy into output buffer */ for (j = 0; j < effp->in_signal.channels; j++) { update_rms(effp, *ibuf); *obuf++ = *ibuf++; nrOfInSamplesRead++; nrOfOutSamplesWritten++; } } /* Case 2 */ else if (!threshold) { /* Add to holdoff buffer */ for (j = 0; j < effp->in_signal.channels; j++) { update_rms(effp, *ibuf); if (silence->leave_silence) { *obuf++ = *ibuf; nrOfOutSamplesWritten++; } silence->stop_holdoff[ silence->stop_holdoff_end++] = *ibuf++; nrOfInSamplesRead++; } /* Check if holdoff buffer is greater than duration */ if (silence->stop_holdoff_end >= silence->stop_duration) { /* Increment found counter and see if this * is the last period. If so then exit. */ if (++silence->stop_found_periods >= silence->stop_periods) { silence->stop_holdoff_offset = 0; silence->stop_holdoff_end = 0; if (!silence->restart) { *isamp = nrOfInSamplesRead; *osamp = nrOfOutSamplesWritten; silence->mode = SILENCE_STOP; /* Return SOX_EOF since no more processing */ return (SOX_EOF); } else { silence->stop_found_periods = 0; silence->start_found_periods = 0; silence->start_holdoff_offset = 0; silence->start_holdoff_end = 0; clear_rms(effp); silence->mode = SILENCE_TRIM; goto silence_trim; } } else { /* Flush this buffer and start * looking again. */ silence->mode = SILENCE_COPY_FLUSH; goto silence_copy_flush; } break; } /* Filled holdoff buffer */ } /* Detected silence */ } /* For # of samples */ } /* Trimming off backend */ else /* !(silence->stop) */ { /* Case B */ memcpy(obuf, ibuf, sizeof(sox_sample_t)*nrOfTicks* effp->in_signal.channels); nrOfInSamplesRead += (nrOfTicks*effp->in_signal.channels); nrOfOutSamplesWritten += (nrOfTicks*effp->in_signal.channels); } break; case SILENCE_COPY_FLUSH: /* nrOfTicks counts non-wide samples here. */ silence_copy_flush: nrOfTicks = min((silence->stop_holdoff_end - silence->stop_holdoff_offset), (*osamp-nrOfOutSamplesWritten)); nrOfTicks -= nrOfTicks % effp->in_signal.channels; for(i = 0; i < nrOfTicks; i++) { *obuf++ = silence->stop_holdoff[silence->stop_holdoff_offset++]; nrOfOutSamplesWritten++; } /* If fully drained holdoff then return to copy mode */ if (silence->stop_holdoff_offset == silence->stop_holdoff_end) { silence->stop_holdoff_offset = 0; silence->stop_holdoff_end = 0; silence->mode = SILENCE_COPY; goto silence_copy; } break; case SILENCE_STOP: /* This code can't be reached. */ nrOfInSamplesRead = *isamp; break; } *isamp = nrOfInSamplesRead; *osamp = nrOfOutSamplesWritten; return (SOX_SUCCESS); }