The data is read into a ByteArrayOutputStream and then as soon as I
stop recording, the stream contents are written to a byte array, using
'toByteArray()'. After that, I can get the size of this byte array,
which gives me the total number of bytes collected, keeping in mind
that I am using 16 bit resolution, i.e., each sound sample is 16 bits
long. I am using a software tone generator, with the frequency set at
500.0 Hertz.
Now, from simple DSP principles, we know that if the number of samples
collected is 'n' and the sampling frequency is 'fs', then the time
needed to collect these 'n' samples is n/fs, and the fundamental
frequency recorded is the inverse of this time value.
However, I am only getting frequencies as low as 7 Hz, or 8Hz, which
is just absurd. Could someone please tell me if I am doing something
totally incorrect, or where the flaw in my reasoning is. Any help
would be greatly appreciated. Thanks in advance for your help.
cpptut...@yahoo.com wrote:
Once I was asked to make a portable program in Java which should do some
signal processing using the low level waveform I/O.
That appeared to be impossible because of many weird problems (mainly
with the different JVM drivers).
So, don't try to use Java for the signal processing, especially at the
waveform i/o level and in the real time. Java is not for that.
Vladimir Vassilevsky
DSP and Mixed Signal Design Consultant
http://www.abvolt.com
> [...]
> Now, from simple DSP principles, we know that if the number of samples
> collected is 'n' and the sampling frequency is 'fs', then the time
> needed to collect these 'n' samples is n/fs, and the fundamental
> frequency recorded is the inverse of this time value.
What's the difference between "sampling frequency" and "fundamental
frequency"? If "fs" is your sampling frequency, then "fs/n" (i.e. "the
inverse of this time value") is a meaningless "per second" value, because
you've removed the "samples" part of the formula.
For example, let's consider a sampling rate of 10 Hz. If you have 10
samples, then your "fs/n" value is "1/second". But if you have 20
samples, without changing the actual sampling rate, your "fs/n" value is
"0.5/second" or "1/(2 seconds)". The actual sampling rate hasn't changed,
but your calculated value -- whatever it's meant to represent -- is
changing.
Obviously lengthing the amount of time so that you can get more samples
doesn't actually change the sampling rate. So if you're trying to use
that "fs/n" to map back to some sort of useful number related to the rate
at which you're sampling, or an audio frequency that you can record, it's
not going to actually do that. "fs/n" is an arbitrary value that is
simply the reciprocal of the number of seconds over which you
recorded...it has nothing to do with the underlying nature of the data
you've recorded, other than being a direct (albeit inverse) measure of the
time duration of the recording.
> However, I am only getting frequencies as low as 7 Hz, or 8Hz, which
> is just absurd. Could someone please tell me if I am doing something
> totally incorrect, or where the flaw in my reasoning is. Any help
> would be greatly appreciated. Thanks in advance for your help.
Perhaps you could be more specific about how you're doing the recording.
A concise-but-complete code sample would not be unreasonable here. That
would allow us to precisely know just how you're capturing the audio data,
as well as how you're calculating your frequencies.
From your paragraph about "fundamental frequency", I think there's a
possibility that you're simply not calculating the "frequency" correctly.
You should first be more clear about what frequency it is you really want
to calculate (are you looking for the sampling frequency here?). And you
should show the code you're using to do that calculation.
Also, "PCM" is by itself somewhat ambiguous. There are some PCM formats
that do some rudimentary compression, by encoding each sample as a
difference from the previous sample (and there are multiple variations on
that technique).
If your frequency calculation is correct (which hasn't been shown to be
true yet), and you can take the bytes you saved, group them in twos and
send them back out to an audio playback interface that takes raw,
uncompressed samples and they sound correct, then I'd agree something's
fishy. But I think it's more likely that either the calculation is simply
wrong, or that if you treat those bytes as raw, uncompressed samples,
you'll get garbage trying to play them back.
In other words, I think it's more likely there's a mistake on your part
than that there's something fishy going on. But then, I get the
impression you know that. :) So really, the key here is for you to
provide enough information for someone to explain what your mistake is.
So far, you haven't.
Pete
You haven't said how long your audio clips are, or what you mean by
'getting frequencies'. I assume you're analyzing them for frequency
content, and finding little or none below 7Hz?
Consider that most audio paths are AC coupled, because humans can't hear
much below 40Hz (or 60, or 20, depending on who you ask). Given that, a
7Hz low-frequency cut off is generously low.
--
Tim Wescott
Control systems and communications consulting
http://www.wescottdesign.com
Need to learn how to apply control theory in your embedded system?
"Applied Control Theory for Embedded Systems" by Tim Wescott
Elsevier/Newnes, http://www.wescottdesign.com/actfes/actfes.html
> Consider that most audio paths are AC coupled, because humans can't hear
> much below 40Hz (or 60, or 20, depending on who you ask). Given that, a
> 7Hz low-frequency cut off is generously low.
>
That's a good point, actually. Even if Java were a DSP system, which it
isn't, you're still at the mercy of whatever cheap-ass hardware is on
the motherboard of your PC. I doubt its up to even a low-end studio rig.
If you're using some sort of audio equipment run by Java that's not a
PC, then you need to contact the manufacturer, 'cause there's no way
we're going to know more than the maker.
Can you elaborate on what the problems were. This really shouldn't be a
problem for Java. I just can't imagine why it would be.
--
Kenneth P. Turvey <kt-u...@squeakydolphin.com>
> Tim Wescott wrote:
>
>> Consider that most audio paths are AC coupled, because humans can't
>> hear much below 40Hz (or 60, or 20, depending on who you ask). Given
>> that, a 7Hz low-frequency cut off is generously low.
>>
>
> That's a good point, actually.
Well, it's a good point if the OP actually meant he's trying to detect
frequencies as low as 7 Hz.
However, given that he specifically said he's using a 500 Hz tone
generator, software-based no less, there's nothing about his post that
makes me think he expects to see actual output frequencies of anything
other than 500 Hz, or that the hardware limitations might apply.
That said, yes...if there's hardware involved and if the OP is actually
trying to get frequencies as low as 7 Hz, well...that's just unrealistic.
:)
Pete
Kenneth P. Turvey wrote:
The task was a special modem operating via the sound card continuously.
It worked fine in Win32/C++, however they wanted to make it platform
independent in Java, so they could use the same code in Windows and for
the different flavors of Linux. There were problems with the
interruptions of the continuous flow of the waveform data depending on
the particular JVM and the particular drivers.
> The task was a special modem operating via the sound card continuously.
> It worked fine in Win32/C++, however they wanted to make it platform
> independent in Java, so they could use the same code in Windows and for
> the different flavors of Linux. There were problems with the
> interruptions of the continuous flow of the waveform data depending on
> the particular JVM and the particular drivers.
That's strange. I could see garbage collection being a problem, but one
would think that such things have a sufficient buffer to make short
delays inconsequential. I guess not.
Which is why I asked the OP (who we haven't heard back from) to clarify.
It sounds like he doesn't quite know what he's doing.
Correct. You have a sample window covering n/fs units
of time.
> and the fundamental
> frequency recorded is the inverse of this time value.
The fundamental frequency recorded depends on the contents
of the actual data, not merely this time value. What does
depend on 1/(n/fs), the inverse of your time value, is the
frequency spacing between successive bins of a DFT/FFT
performed on a sample window of that given length in time
(perhaps proportional to a form of frequency "resolution").
Are you calling some sort of frequency analysis routine
in Java? What is the form of the input and the result?
(scalar or complex vector, data type, data packing, and
etc.)
IMHO. YMMV.
GC is very efficient but had poor real time characteristics.
Often the problems can be resolved by tuning the GC via the many
JVM parameters to do so.
Arne
Exactly. To make it work, I had to tweak many not so obvious parameters
depending on the particular OS, JVM and drivers. That broke the whole
idea of being independent from the platform.
>> GC is very efficient but had poor real time characteristics.
>> Often the problems can be resolved by tuning the GC via the many
>> JVM parameters to do so.
> Exactly. To make it work, I had to tweak many not so obvious parameters
> depending on the particular OS, JVM and drivers. That broke the whole
> idea of being independent from the platform.
Platform independence, or even a different model of the same platform,
has always excluded speed. That is, a program may run faster or slower
but it will give the correct output (bits). Unfortunately, audio
depends not only on the bits but the speed.
-- glen
>> [...]
>> Now, from simple DSP principles, we know that if the number of samples
>> collected is 'n' and the sampling frequency is 'fs', then the time
>> needed to collect these 'n' samples is n/fs, and the fundamental
>> frequency recorded is the inverse of this time value.
> What's the difference between "sampling frequency" and "fundamental
> frequency"? If "fs" is your sampling frequency, then "fs/n" (i.e. "the
> inverse of this time value") is a meaningless "per second" value,
> because you've removed the "samples" part of the formula.
If you have n samples and sampling frequency fs then fs/n is the
lowest frequency you get from, for example, an FFT. That is,
the lowest frequency periodic in n samples. Whether that should
be called fundamental or not, I don't know.
-- glen
You did not have to change the code or even rebuild just the
modify the configuration.
It happen - also for other problem domains than real time.
Arne
For a given signal being sampled for analysis, the number of points
obtained and the time between samples combine to determine the total
length of time taken to examine the signal. The following definitions
apply:
fs = sample rate in Hz
dT = 1/fs = interval between samples
N = number of samples taken
T = N x dT = total time period
f1 = 1/T = frequency of the first harmonic in Hz
Keeping these points in mind, I have found that f1 in my case is
around 7 Hz. I am NOT measuring 7 Hz. If I were to take an FFT of the
collected data, then I can expect to get peaks that are harmonics of 7
Hz. That is if I were to detect if the 500.0 Hz signal of the tone
generator was being picked up, I would have look for the 500/7
harmonic of 7 Hz. I hope I have made myself clear about what I am
trying to do.
On Apr 13, 4:14 pm, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com>
wrote:
> On Sun, 13 Apr 2008 13:44:36 -0700, cpptutor2...@yahoo.com
Sure, but please do not top-post, and please do trim what you quote.
> For a given signal being sampled for analysis, the number of points
> obtained and the time between samples combine to determine the total
> length of time taken to examine the signal. The following definitions
> apply:
> fs = sample rate in Hz
> dT = 1/fs = interval between samples
> N = number of samples taken
> T = N x dT = total time period
>
> f1 = 1/T = frequency of the first harmonic in Hz
So if you accumulated twice as many samples, over twice as long, your
fundamental frequency would be halved? That is not sensible.
--
Lew
You are using non-standard DSP vocabulary. 500 Hz is your
fundamental, not 7 Hz. 7 Hz might be your DFT bin separation,
bin resolution, or spacing.
You also never answered whether you tried plotting your
data after the type conversion to make sure you didn't
clip or wrap it.
> Could some DSP or Java guru please help me ? I have a simple
> Java
> application that records audio signals and does simple
> analysis on the
> collected data. I am using PCM encoding, with sampling
> frequency 16000
> Hz, 16 bits resolution, single or mono channel, little endian
> and
> signed.
Did you properly reconstruct the shorts or ints from the byte
data? One way to tell is to look at the range of your
reconstructed data (the difference between maximum and minimum)
over an interval. If the range is 32767 to 32768 (or 0 to
65536, or some such) that can be a strong hint that your bytes
are assembled backwards. In this case, a plot of the data
should look like rail-to-rail noise.
>
> The data is read into a ByteArrayOutputStream and then as
> soon as I
> stop recording, the stream contents are written to a byte
> array, using
> 'toByteArray()'. After that, I can get the size of this byte
> array,
> which gives me the total number of bytes collected, keeping
> in mind
> that I am using 16 bit resolution, i.e., each sound sample is
> 16 bits
> long. I am using a software tone generator, with the
> frequency set at
> 500.0 Hertz.
>
> Now, from simple DSP principles, we know that if the number
> of samples
> collected is 'n' and the sampling frequency is 'fs', then the
> time
> needed to collect these 'n' samples is n/fs, and the
> fundamental
> frequency recorded is the inverse of this time value.
>
> However, I am only getting frequencies as low as 7 Hz, or
> 8Hz, which
> is just absurd.
However, in a later post you wrote:
> f1 = 1/T = frequency of the first harmonic in Hz
> Keeping these points in mind, I have found that
> f1 in my case is around 7 Hz. I am NOT measuring
> 7 Hz. If I were to take an FFT of the collected
> data, then I can expect to get peaks that are
> harmonics of 7 Hz. That is if I were to detect
> if the 500.0 Hz signal of the tone generator was
> being picked up, I would have look for the 500/7
> harmonic of 7 Hz. I hope I have made myself clear
> about what I am trying to do.
Even (especially) after reading your later post, I don't
understand what you are saying. From your later post, it seems
that 7 Hz is your bin resolution, so the first bin corresponds
to 7 Hz, the 2nd to 14 Hz, etc. Are you saying that you don't
see a spike near bin 71 (500/7)? Perhaps the amplitude of your
injected tone is too low compared to the amplitude of your
other signal (so the spike is there, it's just lost in the
noise). What exactly is the problem?
I did plot the data, after the type conversion. I find the following
(typical data sample length 2048 doubles):
1. a few spikes at the start - most probably due to a large DC offset
being introduced somewhere.
2. a large sequence of zeros - about 250 - 300 samples long
3. the sinusoidal curve that one would expect - a little bit noisy,
but still okay.
> Even (especially) after reading your later post, I don't
> understand what you are saying. From your later post, it seems
> that 7 Hz is your bin resolution, so the first bin corresponds
> to 7 Hz, the 2nd to 14 Hz, etc. Are you saying that you don't
> see a spike near bin 71 (500/7)? Perhaps the amplitude of your
> injected tone is too low compared to the amplitude of your
> other signal (so the spike is there, it's just lost in the
> noise). What exactly is the problem?
The problem is, as I mentioned in a posting just before, that when I
plot the data, I see a long sequence of zeros, about 250 - 300 sample
points long, before I see the sinusoidal signal. There are a few sharp
and large spikes at the start, which might be due to DC offset, but I
do not understand the sequence of zeros. The total sample size of the
collected data is 2048.
> > fs = sample rate in Hz
> > dT = 1/fs = interval between samples
> > N = number of samples taken
> > T = N x dT = total time period
>
> > f1 = 1/T = frequency of the first harmonic in Hz
>
> So if you accumulated twice as many samples, over twice as long, your
> fundamental frequency would be halved? That is not sensible.
>
> --
> Lew
That is precisely the case. Please check the definitions above. Please
note that f1 is the first harmonic if I were to calculate an FFT with
the collected samples. The fundamental frequency is 500.0 Hz, and
stays that way.
Pete,
It would help if you used the same terms that the rest of us do. In
particular, it is important to avoid using standard words in
non-standard ways without the sort of glossary you provided here.
*Fundamental* applies not to an FFT, but to the longest-period component
of a periodic waveform. What *you* have called the fundamental is often
referred to as bin width or resolution.
If your signal repeats every 2 ms, then its fundamental is 500 Hz. It
may have harmonics at 1000, 1500, 2000Hz, etc.
Jerry
--
Engineering is the art of making what you want from things you can get.
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
It could be a data header. Or it could be how long it
takes your mic or ADC to initialize. Why not just ignore
this header or turn-on transient?
Does your sinusoid have roughly balanced positive and
negative values? Or do you have a DC offset of your
sinusoid?
Look to the acquisition software. It's unlikely that there's a
startup-transient that large in the hardware, but there may be an offser
between the pointers that write the data and retrieve it.
Look to the acquisition software. It's unlikely that there's a startup
transient that large in the hardware, but there may be an offset
between the pointers that write and retrieve the data.
I'll second Ron's motion and add that some file formats that
I'm familiar with reserve the first 512-byte block (or more)
for "metadata"; that is, special labels that identify things
about the data like the sample rate, the number of bits per
sample, the endian-ness, whether stereo or mono, the number of
channels, etc. Since these things don't often consume all the
allocated space, the remaining bytes ("reserved for future
expansion" is a favorite phrase here) are often set to zero.
As long as identifiable data starts at a constant offset from
the beginning of the file and assuming that you don't need the
metadata, my advice would be to read it and discard it.
No, that doesn't make sense. If I recorded a pure 1000 Hz sine wave, that is
the frequency whether I take 44000 samples for one second or 88000 samples
over two seconds. The frequency isn't affected by how long I record it.
--
Lew
No wonder I was confused. It was a case of, "There's glory for you!"
(Carroll, Lewis, /Through the Looking-Glass/, Chapter VI, "Humpty Dumpty",
<http://www.gutenberg.org/etext/12>).
--
Lew
One way to 'cut through the c..onfusion' is to post an
SSCCE. More info here
http://sscce.org/
Have one peice of code to generate the tone,
and a second to do the transform.
--
Andrew T.
The frequency *resolution* is, though. That's what the OP was referring to
[rather obliquely]. The OP mistakenly calls this the fundamental frequency.
The sampling rate determines the bandwidth, and the maximum freq. which you can
capture (Nyquist-Shannon). The overall length (in time, not samples) determines
the frequency resolution (Fourier).
--
Nigel Wade
> It would help if you used the same terms that the rest of us do. In
> particular, it is important to avoid using standard words in
> non-standard ways without the sort of glossary you provided here.
> *Fundamental* applies not to an FFT, but to the longest-period component
> of a periodic waveform. What *you* have called the fundamental is often
> referred to as bin width or resolution.
It does make some sense in the context of the FFT, though.
Since FFT has periodic boundary conditions, the lowest non-zero
frequency could be considered the fundamental. Those who
apply the FFT to non-periodic signals get what they deserve.
> If your signal repeats every 2 ms, then its fundamental is 500 Hz. It
> may have harmonics at 1000, 1500, 2000Hz, etc.
-- glen
> > snip
> It does make some sense in the context of the FFT, though.
> Since FFT has periodic boundary conditions, the lowest non-zero
> frequency could be considered the fundamental.
In the OP's description, 500 Hz is the lowest non-zero frequency :,).
And it is the 'fundamental of the signal', as opposed belonging to the
set of 'fundamental frequencies of the transform', of which zero is
included as a member.
Does anyone have a suggestion for a description of this area of
vocabulary that is:
1) accessible (free, etc.)
2) complete enough for this level of discussion
3) unambiguous
4) at a suitable level for the OP?
> Those who
> apply the FFT to non-periodic signals get what they deserve.
>
Those who have known how to apply the FFT to non-periodic signals have
made much good use of it.
> -- glen
Dale B. Dalrymple
I thought you (amongst others) might like that URL.
It is Dave Minter's mirror of the SSCCE. Thanks Dave!
--
Andrew T.