问题
This might be more of a math question than an R question but here it goes...
I'm trying to generate a low frequency oscillator (LFO2) where the frequency is controlled by another low frequency oscillator (LFO1). LFO1 has a frequency of 0.02 Hz while I want LFO2 to have a frequency that oscillates between 0.00 and 0.11 Hz dependent on the output of LFO1.
# length in seconds
track_length <- 356
upsample <- 10 # upsample the signal
# LFO rates (Hz)
rate1 <- 0.02
rate2_range <- list(0.00, 0.11)
# make plot of LFO1
x1 <- 1:(track_length*upsample)/upsample
amp <- (rate2_range[[2]] - rate2_range[[1]])/2
y1 <- amp*cos(2*pi*rate1*x1) + amp
plot(x1, y1, type='l')
The variable frequency for LFO2 generated by LFO1 looks exactly as I expected.
So I go on to make LFO2 using the output of LFO1 like so..
# make plot of LFO2
x2 <- x1
y2 <- cos(2*pi*y1*x2)
plot(x2, y2, type='l')
However, the output of LFO2 is not what I expected... It seems to be continuously getting faster and also has some peaks that don't oscillate at the full range. I don't understand this as the only thing I'm adjusting is the frequency and it shouldn't be faster than 0.11 Hz. At first I thought it might be an under sampling issue but I get the same results when upsampling the time series to any degree.
Any idea what I'm missing here?
回答1:
The "frequency" of cos(f(t)) is not f(t). It's the derivative of f(t). You have:
y1(t) = A*cos(2πf1t) + A
y2(t) = cos(2πy1(t))
If the frequency you want is Acos(2πf1t) + A, then you need to integrate that to get the argument to cos:
y1(t) = A*sin(2πf1t)/2πf1 + At
y2(t) = cos(2πy1(t))
In R:
# length in seconds
track_length <- 356
upsample <- 10 # upsample the signal
# LFO rates (Hz)
rate1 <- 0.02
rate2_range <- list(0.00, 2)
# make integral of LFO1
x1 <- 1:(track_length*upsample)/upsample
amp <- (rate2_range[[2]] - rate2_range[[1]])/2
y1 <- amp*sin(2*pi*rate1*x1)/(2*pi*rate1) + amp*x1
plot(x1, y1, type='l')
# make plot of LFO2
x2 <- x1
y2 <- cos(2*pi*y1 / upsample)
plot(x2, y2, type='l')
回答2:
You are not restricting the data by amp as you did at the first plot. So it is normal to see cos output altering around -1 and 1.You need to restrict the formula by the max(y1)
and min(y1)
.
So the codes below,
y2 <- vector()
amp <- (max(y1) - min(y1))/2
for(i in 1:length(y1)) {
y2[i] <- amp * cos(2*pi* y1[i] * x2) + amp
}
plot(x2, y2, type='l',col="blue")
grid(nx = NULL, ny = NULL, col = "lightgray", lty = "dotted")
gives this plot,
来源:https://stackoverflow.com/questions/57347005/r-generate-sine-wave-with-variable-frequency