30

Is there something like a stereo (separate left-and right-channel) tone-generator for Linux? Where you can set volume and tone/pitch for each channel, and preferably also set the wave-form (sine, square, sawtooth, ...) and invert one channel (as opposed to the other).

If not, any ideas for a good places to start to make one? I guess the simplest would be to adapt existing programs like synths... But if that work poorly, are there any libraries (like SDL?) that can be used as bases for such a program?

2

8 Answers 8

24

It sounds like you're looking for Audacity which is a cross-platform open source audio editor. One of its features is to allow you to generate tones. It's a multi-track audio editor, so you can easily create a stereo tone.

Under the Generate menu, you're able to create Sine, Sawtooth, and Square waveform tones of arbitrary frequency, amplitude, and length without the need for recording or needing additional input files.

2
  • But can it generate tones "from nothing"? And I'm not intending to record and playback anything, just generate two slightly different tones (one for each channel) "for eternity". Commented Jul 7, 2013 at 18:38
  • 1
    @BaardKopperud Yes, I updated my answer to clarify.
    – j883376
    Commented Jul 7, 2013 at 18:47
22

ffmpeg

ffmpeg can do it, as usual.

Create a 2 second mono 1000 Hz sinusoidal out.wav sound file:

sudo apt-get install ffmpeg
ffmpeg -f lavfi -i "sine=f=1000:d=2" out.wav

Stereo instead with -ac 2:

ffmpeg -f lavfi -i "sine=f=1000:d=2" -ac 2 out.wav

The file will be 2x as large, and ffprobe will say it has 2 channels instead of 1 channel.

Generate 2 seconds of 500 Hz on left and 1000 Hz on right, related question: https://stackoverflow.com/questions/59551013/how-to-generate-stereo-sine-wave-using-ffmpeg

ffmpeg -filter_complex '
sine=f=500[0];
sine=f=1000[1];
[0][1]amerge,atrim=end=2
' out.wav

Play the 1000 Hz for 2 seconds without creating a file:

ffplay -autoexit -nodisp -f lavfi -i 'sine=f=1000:d=2'

Play 1000 Hz forever until you go mad:

ffplay -nodisp -f lavfi -i "sine=f=1000"

Produce a 2 second mixture/overlay of 500 Hz and 1000 Hz on both channels, related question: https://stackoverflow.com/questions/14498539/how-to-overlay-downmix-two-audio-files-using-ffmpeg

ffplay -nodisp -autoexit -f lavfi -i '
sine=f=500[0];
sine=f=1000[1];
[0][1]amix=inputs=2, atrim=end=2
'

Produce 2 seconds of 500 Hz followed by 2 seconds of 1000 Hz:

ffplay -nodisp -autoexit -f lavfi -i '
sine=f=500:d=2[0];
sine=f=1000:d=2[1];
[0][1]concat=n=2:v=0:a=1
'

2 seconds of 250 Hz + 500 Hz followed by two seconds of 1000 Hz + 2000 Hz:

ffplay -nodisp -autoexit -f lavfi -i '
sine=f=250[0];
sine=f=500[1];
sine=f=1000[2];
sine=f=2000[3];
[0][1]amix=inputs=2, atrim=end=2[01];
[2][3]amix=inputs=2, atrim=end=2[23];
[01][23]concat=n=2:v=0:a=1[out];
'

Frequency sweep from 0 to 20 kHZ over 10 seconds, main question: https://superuser.com/questions/1156429/how-to-generate-a-time-dependent-frequency-wave/1156468#1156468

ffplay -autoexit -f lavfi -i "aevalsrc='sin(2000*t*2*PI*t)':d=10" 

Documentation:

The other section sunder Audio sources document other useful sound generation algorithms in addition to sine, e.g.:

  • anoisesrc: noises of several colors, e.g. white, pink, brown
  • aevalsrc takes arbitrary mathematical expressions, and should therefore be able to produce triangular waveforms (TODO expression)

Bibliography:

Tested on ffmpeg 6.0, Ubuntu 23.10.

Minimal C audio generation example without extra libraries

Just for fun: https://stackoverflow.com/questions/732699/how-is-audio-represented-with-numbers-in-computers/36510894#36510894

12

You might look at speaker-test, which (on an Arch machine) I find in alsa-utils package.

speaker-test -c2 -t sine run from an xterm, gave me a 440 Hz sine wave for about 6 seconds each, alternating left and right speakers. In the xterm, it gave some information about which speaker it thought it was using.

According to the man page, it can do sine waves of arbitrary frequency and pink noise.

3
  • 4
    speaker-test -c2 -t sine -f 440 will complement your example by giving the frequency parameter. Thanku.
    – christian
    Commented Jun 3, 2018 at 12:37
  • 1
    It's worth mentioning that the frequency parameter apparently has no effect without -t sine, since the -t option default is pink noise. Commented Oct 20, 2020 at 9:23
  • This tool makes 8000Hz at most, in my case.
    – Dmitry
    Commented Apr 28, 2023 at 12:57
6

The siggen program should do the trick.

screenshot of siggen

It has two channels with independent signals and a phase between them. Each channel can do these signal types:

  • sine
  • cosine
  • square
  • triangle
  • sawtooth
  • pulse
  • noise

You can run it in stereo mode like this:

siggen -2

Note that this relies on /dev/dsp which was provided by OSS. OSS was superseded by ALSA and deprecated around 2006, so you will probably need to install a compatibility library. On Debian-based distros, install the alsa-oss package and run it like this:

aoss siggen -2

You can also try it with the PulseAudio OSS Wrapper which is provided with the pulseaudio-utils package:

padsp siggen -2
3
  • I get: [siggen] Input/output error : /dev/dsp
    – Ole Tange
    Commented Apr 17, 2019 at 19:47
  • Hm. Does the PulseAudio OSS wrapper help at all? Commented Apr 17, 2019 at 20:02
  • Yep. It worked.
    – Ole Tange
    Commented Apr 18, 2019 at 7:14
3

The saugns program can also do it. (It is a command-line audio generator supporting a language including more types of audio generation, including centrally FM/PM and AM/RM modulation techniques.)

To generate two stereo-separated 100 Hz waves, one a sine and one a triangle, and one with inverted amplitude, the following script can be pasted into a file and ran through the program (as in ./saugns filename):

Wsin f100 a0.5 t2 cL
Wtri f100 a(-0.5) t2 cR

This is also short enough that it can instead simply be ran as a one-liner directly:

./saugns -e "Wsin f100 a0.5 t2 cL Wtri f100 a(-0.5) t2 cR"

The ts specify time, in seconds.

The cs are for changing the channel mixing (L = hard left, R = hard right) from the default (C = center). Any numbers from "(-1.0)" to "1.0" can also be used for such values.

Old edit: I'm indeed the developer of the program.

Also, an alternative way of flipping the amplitude (for some wave types, e.g. sin but not saw), is to set the phase using a lowercase p. Adding p0.5 sets phase to 50% of the wave cycle (negative half). Further, as there's no named cosine type, p0.25 is the way to turn sine into cosine (or p0.75 for negative cosine).

1
  • Hi Joel. Welcome to Unix & Linux. I've upvoted your answer as it's a great first post. I thought I'd mention that if you're a maintainer or developer of a project, it's standard practice to disclose this information. While not really an issue for GPL software, it's worth being aware of unix.stackexchange.com/help/promotion For useful Free/Libre software, I'd imagine that you'd be more likely to get upvoted on this site if users know you're one of the developers behind the project. Commented Jun 20, 2019 at 0:17
1

You can easily synthesize tones with SoX. There were some stumbling blocks but I was eventually able to figure it out.

I had trouble interfacing SoX with PulseAudio so I just pipe sox raw data into paplay.

The pipeline is tedious so I created a script:

$ cat sox-paplay
#!/bin/bash
: ${HZ:=44100}
: ${NCHAN:=6}
: ${SINK:=mysink}
sox -c $NCHAN -n -t raw -r $HZ -L -b 16 - "$@" | paplay --no-remix --no-remap --raw -v -p --rate $HZ -d $SINK --channels $NCHAN

e.g.

sox-paplay synth sine 1000 gain -5 remix -m 0 0 1 0 0 0

The remix effect is just used to send the result to a specific channel. It is much more powerful but we only use the basic functionality here. In this example we have a six-channel device and we're sending a tone to the third channel.

I originally created an ALSA device wrapping the PulseAudio device, but then I found that it is impossible to control the channel mapping using ALSA, and so random channels were getting mixed together according to how my custom channel-map differed from the ALSA default. This is why I have --no-remix --no-remap in paplay above; I just want the raw channel ordering for the sox command.

I kind of wish that audio stuff on Linux had better documentation and error reporting.

You may be interested in an answer I posted recently showing how to set the PulseAudio Equalizer from the command-line.

1
play -n synth sine 1000 gain -5 remix -m 0 0 1 0 0 0
2
0

You might be looking for Gnaural.

1
  • 4
    It would be best to edit this answer to include more information about how this program provides the features being asked about - similar to the other answers previously posted. Commented Aug 17, 2018 at 17:46

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .