Sine wave making no sound

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.

Jacob

Posted 2014-07-29T07:22:56.107

Reputation: 131

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 – 2014-07-29T09:32:11.353

2This question is perhaps better suited for a programming q&a site, have you tried that? – Arnoud Traa – 2014-07-29T11:00:51.627

@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 – 2014-07-29T11:06:31.413

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 – 2014-07-29T12:40:14.873

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 – 2014-07-29T14:21:20.817

I suppose the part asking about if a simple sine wave should be audible, or is more needed, is a valid and on-topic question, but I think trying to figure out why the program isn't producing audible output is probably off topic. Perhaps some re-focusing of the question would be sufficient. – AJ Henderson – 2014-07-29T14:26:29.137

I debated with myself whether to post this on Stack Overflow, because of the programming, this site, because of understanding of sound, or Super User, because of sox. I chose this one because I thought there'd be the most likelihood that someone understands audio formats and sound in general. I'll look into posting the files themselves tonight if I don't get an answer. – Jacob – 2014-07-29T15:53:46.387

If you can point us to a copy of the file, it would be simple to analyze it to see if indeed it is a valid file with the characteristics you think it has. Until then it's unclear if this is a design issue, a programming issue, a file format issue etc. – Jim Mack – 2014-07-29T16:05:32.113

Are you sure you're not producing a DC (all positive) signal? It looks this way to me. The function to generate a 261.62Hz sine wave would be y=SIN(261.63 * x), where y is the amplitude and x is time. This will give you an AC wave. Since 16 bit wave files use signed integers the values need to alternate between +/- values to produce audible sound. – audiomason – 2014-07-29T17:54:01.247

I am producing all positive signals; my sox parameters specify that values are unsigned integers, but maybe it doesn't support it for 16-bit. I'll try playing with that instead. – Jacob – 2014-07-29T20:18:22.677

At any rate please post some precise information about what you have there since at the moment this is blind guessing here. – leftaroundabout – 2014-07-29T22:34:02.753

Precise information? I think I've been precise. I've added a link to the WAV file. I'm thinking @audiomason may have the right idea; I'm going to try floating-point samples instead and see if that helps. – Jacob – 2014-07-30T02:22:40.150

Drat, @audiomason, even with signed (twos complement) 16-bit samples, I can't hear anything. – Jacob – 2014-07-30T05:35:08.173

Answers

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.

leftaroundabout

Posted 2014-07-29T07:22:56.107

Reputation: 5 941

You are simply amazing. I will try the fix! – Jacob – 2014-07-30T15:43:11.197

Yes, that worked perfectly. – Jacob – 2014-07-30T15:44:55.890