-
Notifications
You must be signed in to change notification settings - Fork 3
/
sparse-fr-spectrum.R
127 lines (115 loc) · 3.24 KB
/
sparse-fr-spectrum.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#' @keywords internal
.sparse_fr_spectrum <- function(frequency, amplitude) {
checkmate::qassert(frequency, "N")
checkmate::qassert(amplitude, "N")
stopifnot(length(frequency) == length(amplitude))
res <- sparse_spectrum(x = frequency,
y = amplitude,
x_unit = "Hz",
y_unit = "amplitude",
label = "sparse frequency spectrum",
x_lab = "Frequency (Hz)",
y_lab = "Amplitude")
class(res) <- c("sparse_fr_spectrum", "chord", class(res))
res
}
#' Is sparse pitch-class spectrum
#'
#' Checks whether an object belongs to the class \code{sparse_fr_spectrum}.
#'
#' @param x Object to check.
#'
#' @return Logical scalar.
#'
#' @export
is.sparse_fr_spectrum <- function(x) {
is(x, "sparse_fr_spectrum")
}
#' Sparse frequency spectrum
#'
#' This function represents an input object as a
#' sparse frequency spectrum.
#'
#' @details
#' A sparse frequency spectrum comprises a finite set of spectral components,
#' each defined by a frequency (in Hz)
#' and an amplitude (expressed in arbitrary units, but with the
#' fundamental frequencies of chord pitches typically taking the value 1).
#'
#' @param x Input sonority.
#' * Numeric vectors will be treated as vectors of MIDI note numbers,
#' and expanded into their implied harmonics.
#' * Two-element lists will be treated as finalised spectra.
#' The first element should be labelled "frequency",
#' and correspond to a numeric vector of frequencies;
#' the second element should be labelled "amplitude",
#' and correspond to a numeric vector of amplitudes.
#'
#' @inheritDotParams expand_harmonics
#'
#' @return An object of class \code{sparse_fr_spectrum}.
#'
#' @rdname sparse_fr_spectrum
#'
#' @md
#'
#' @export
sparse_fr_spectrum <- function(x, ...) {
UseMethod("sparse_fr_spectrum")
}
#' @rdname sparse_fr_spectrum
#' @export
sparse_fr_spectrum.sparse_fr_spectrum <- function(x, ...) {
x
}
#' @rdname sparse_fr_spectrum
#' @export
sparse_fr_spectrum.sparse_pi_spectrum <- function(x, ...) {
.sparse_fr_spectrum(
frequency = midi_to_freq(pitch(x)),
amplitude = amp(x)
)
}
#' @rdname sparse_fr_spectrum
#' @export
sparse_fr_spectrum.pi_chord <- function(x, ...) {
sparse_fr_spectrum(sparse_pi_spectrum(x, ...))
}
#' @rdname sparse_fr_spectrum
#' @export
sparse_fr_spectrum.default <- function(x, ...) {
sparse_fr_spectrum(pi_chord(x), ...)
}
#' @rdname sparse_fr_spectrum
#' @export
sparse_fr_spectrum.list <- function(x, ...) {
stopifnot(length(x) == 2L,
is.numeric(x[[1]]),
is.numeric(x[[2]]),
length(x[[1]]) == length(x[[2]]))
stopifnot(is.null(names(x)) || identical(names(x), c("frequency", "amplitude")))
.sparse_fr_spectrum(frequency = x[[1]],
amplitude = x[[2]])
}
#' @export
freq.sparse_fr_spectrum <- function(x) {
x$x
}
#' @export
`freq<-.sparse_fr_spectrum` <- function(x, value) {
stopifnot(is.numeric(value),
length(value) == length(freq(x)))
x$x <- value
x
}
#' @export
amp.sparse_fr_spectrum <- function(x) {
x$y
}
#' @export
`amp<-.sparse_fr_spectrum` <- function(x, value) {
stopifnot(is.numeric(value),
length(value) == length(amp(x)))
x$y <- value
x
}