2

I'm experimenting with generating sound programmatically. As I understand the math, I think I'm creating a 5-second long mono-channel sine wave at the frequency of "middle C," but when I play back the audio data, I cannot hear anything.

Let me explain how I'm creating the data, and maybe you can tell what I'm doing wrong.

  1. I start with a sine wave; I am dividing the time parameter by 2 * pi so that the function repeats for every one unit; this is to hopefully simplify the math:
  2. To set the pitch of this wave, I multiply the time parameter by 261.63, so that it will oscillate at the frequency for middle C.
  3. I sample the function 44100 times per second, for 5 seconds.
  4. For each sample value, I add 1, so that values range from 0 to 2.
  5. Each sample value is multiplied by 215, giving me a range from 0 to 65536 (16 bits).
  6. I output, in little-endian format, each 2-byte value in sequence.

When inspecting the raw audio data in a hex editor, it looks correct to me; values start mid-range at 0x8000, go up to 0xffff, go back down to 0x0000, go back up to 0xffff, etc. It resembles what I'd expect a sine wave to look like, taking up the full dynamic range of 16 bit values.

So given this raw data, I convert it through sox to a WAV file (line breaks added for clarity):

sox
  -t raw
  -b 16
  -r 44100
  -e unsigned-integer
  --endian little
  input.raw
  output.wav

The wave file is successfully created and looks valid from what I can tell. Playback works for the file, and visualization during playback shows there's something being output, but I can't hear a thing. I tried playing with the amplitude of the wave to reduce the dynamic range, but that didn't help.

I am extremely new to sound, and am just now learning all the theory behind it. Is the mathematical approach correct for producing a tone? Am I doing something wrong with my data formatting? Am I using sox incorrectly? What could be the problem here?

(I decided to not include all my Haskell code, but if it would help, I can post it here. However, as I stated, the data resembles a sine wave, so I have no idea why there's no sound.)

Edit:

Here's a link to the file.

Edit 2:

I created new samples that are signed 16-bit values, then converted to a WAV with this:

sox
  -t raw
  -b 16
  -r 44100
  -e signed-integer
  --endian little
  input.raw
  output.wav

The output from that is this. Unfortunately, it still is inaudible.

  • I think it would help if you posted your code, especially if it's something nice as Haskell! – The most likely reason why you don't hear anything seems that you're generating infrasound for some reason. – leftaroundabout Jul 29 '14 at 9:32
  • 2
    This question is perhaps better suited for a programming q&a site, have you tried that? – Arnoud Traa Jul 29 '14 at 11:00
  • @ArnoudTraa: I disagree, it's not about "why does my program not produce the signal I want" but about "why is this signal which my program yields not audible", which has nothing do to with programming so SoundDesign is definitely a better location than a StackOverflow. I just asked the OP to post the code so the problem is reproducible, but he might as well post the audio file. – leftaroundabout Jul 29 '14 at 11:06
  • Hi leftaroundabout, I agree with the distinction between the two issues, that's why i wrote perhaps. I don't want to say programming sounds with SOX i not sound design, but then again, i think there should be better places to discuss this topic. That would help keep this site in focus (sound design). But I must admit that this might also be a sound design topic... it's a grey area. – Arnoud Traa Jul 29 '14 at 12:40
  • I have created a Meta Post to discuss if this kind of question is on topic. Personally, my vote would be with ArnoudTraa that this is a programming question. If it is actually producing a sine wave and proper audio file, it should be audible, the fact it is not means there is a bug in the program, which means this is debugging. I don't see how debugging is sound design or even audio production. – AJ Henderson Jul 29 '14 at 14:21
6

Your sine has come out a couple of octaves too low, for some reason. Indeed it's infrasound, 6.6 Hz to be precise, which rather explains why you don't hear anything.

A couple of ways you could have found this out:

  • Actually the sound is still "audible": over a decent subwoofer, you'll hear (or rather feel) a throbbing similar to a ship engine, and things in your room might start to clatter in an audible way.
  • Pretty much any audio player nowadays has some kind of primitive spectrum view. With your file, it'll show quite some signal in the low-frequency end, but nothing elsewhere: Audacious spectrum view
  • Any audio editor / DAW shows the waveform. Audacity will do: Waveform in audacity Here you can immediately see that there's a perfectly correctly scaled signal, amplitude-wise, but with just a few cycles per second: certainly not 261. In fact you can easily count them by hand, though there's also tools to do this for you.
  • If I was you, I had just toyed around with the program's parameter's a bit: asking it for a frequency of 5 kHz would have given a well-audible 127 Hz, roughly B1. That would have pointed to the problem a bit more clearly.

So what is the problem, now? Well, we can reverse-engineer those 6.6 Hz. You've used the numbers 261.63, 2π, 5 and 44100. The last one is so big it's unlikely to play a role, but guess-combining the other ones reveals what's going on:

GHCi, version 7.8.2: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> 2 * pi
6.283185307179586
Prelude> 261.63 / 5
52.326
Prelude> 261.63 / (5 * 2 * pi)
8.327941552226516
Prelude> 261.63 / (2 * pi)
41.63970776113258
Prelude> 261.63 / (2 * pi * 6.6)
6.309046630474633
Prelude> 261.63 / (2 * pi)^2
6.627165319086208

Bingo. So you need to multiply the frequency twice by 2π. Why is this? Well actually it would have been clear even from properly reading the question:

I am dividing the time parameter by 2 * pi

This is of course wrong. The 2π are the period length of a RAD sine, so you need to multiply the time by it, not divide. Dividing instead of multiplying leaves you with a factor of (2π)2 short, which is the reason for your wrong frequency.

  • You are simply amazing. I will try the fix! – Jacob Jul 30 '14 at 15:43
  • Yes, that worked perfectly. – Jacob Jul 30 '14 at 15:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.