@@ 484,3 484,69 @@ structure SubBandPeakPick = struct
end
end
+
+(** A specialisation of SubBandPeakPick for use when the vector
+ represents bins from a STFT output, in which the bin index is
+ proportional to frequency.
+ *)
+structure SpectralPeakPick = struct
+
+ (** A sub-band, specified by start and end frequencies. If end is
+ NONE, the band continues to the end of the origin vector. The
+ p-parameter is used for peak picking within the band.
+ *)
+ type band = { f0 : real, f1 : real option, p : int }
+
+ (** A list of sub-bands. The bands do not have to be contiguous
+ and may even overlap, though that is probably undesirable as
+ it may mean returning duplicate peaks.
+ *)
+ type bands = band list
+
+ (** Convert a band to make it usable by SubBandPeakPick directly
+ *)
+ fun mapBand { rate, n } ({ p, f0, f1 } : band)
+ : SubBandPeakPick.band =
+ let val binFor = Pitch.binForFrequency { rate = rate, n = n }
+ val start = floor (binFor f0)
+ in
+ { p = p,
+ start = start,
+ count = Option.map
+ (fn f1' => (ceil (binFor f1' + 1.0e~8) - start))
+ f1
+ }
+ end
+
+ (** Return a list of indices of local peaks within the vector,
+ dividing it up into sub-bands following the given band
+ list. The parameter n is the number of bins, used for
+ conversion between frequency and bin number; the supplied
+ vector does not need to have all n bins but it must start at
+ nominal bin zero (DC).
+ *)
+ fun findPeaks { bands : bands,
+ rate : SignalTypes.rate,
+ n : int
+ } (v : RealVector.vector)
+ : int list =
+ SubBandPeakPick.findPeaks {
+ bands = map (mapBand { rate = rate, n = n }) bands
+ } v
+
+ (** Return a list of indices of local peaks within the vector,
+ dividing it up into sub-bands following the given band list
+ with boundaries snapped to their nearest (simple) trough bin.
+ *)
+ fun findPeaksSnapped { bands : bands,
+ rate : SignalTypes.rate,
+ n : int,
+ resolveDownwards : bool
+ } (v : RealVector.vector)
+ : int list =
+ SubBandPeakPick.findPeaksSnapped {
+ bands = map (mapBand { rate = rate, n = n }) bands,
+ resolveDownwards = resolveDownwards
+ } v
+
+end