-3

I need to make a function in Java that adds a note of a certain frequency and length to audio. I have the frequency as a double, and the note length in milliseconds.

Full Function Description:

This method takes one AudioInputStream and adds the sound of a certain pure frequency to the FRONT of it, lasting a certain length of time. So the method takes two additional parameters: frequency and noteLengthInMilliseconds. The amplitude of the additional sound should be 64*256.

However, I need to find the note's length in Frames, as well as in Bytes and Ints.

Also, any advice on how to create the note as a data array of samples (am using java.sound.sampled package) would be helpful.

FRAME & SAMPLE RATE: 44100.0hz
ENCODING: PCM_SIGNED

Markeazy
  • 76
  • 10

2 Answers2

1

Since your frame rate and sample rate are identical, let's assume you're referring to PCM frames. A PCM frame is one sample per channel. If you only have one audio channel, at 16 bits per sample, you get one frame every two bytes. If you have stereo audio at 16 bits per sample, you get one frame every four bytes.

To figure out the length, take the sample rate and divide it out. If I have a sample rate of 44.1 kHz and I want a note to last for a half second:

44,100 * 0.5 = 22,050 samples (22,050 frames)

From there if you know that the audio is 16 bits, and there is only one channel:

22,050 * 2 (bytes per channel) * 1 (channels) = 44,100 bytes
Brad
  • 159,648
  • 54
  • 349
  • 530
  • So if I have the length in Milliseconds and the sample rate of 44.1 kHz, with 2 channels i'd simply do: `(44,100 * noteLengthInSeconds) * 2 (bytes per channel) * 2 (channels)`? – Markeazy Mar 01 '17 at 00:56
  • Yes. Don't forget to convert your milliseconds to seconds. – Brad Mar 01 '17 at 01:47
1

The length in frames is a simple computation that relies on information in the AudioFormat. Specifically, inspect the property "frameRate". The number of bytes per frame is covered by the frameSize property.

To make your array of audio data involves a couple steps. The values of a pure tone can be created by running a Math.sin function. Math.PI * 2 is equivalent to one full cycle (I do hope you already know this--this is very elementary), so use division to figure out how small an increment for each step.

The result of a Math.sin function is a double between -1 and 1. You will have to convert this number to a data range that fits the assignment. This is done by multiplying the audio value by a factor. For example, multiplying by 32767 would result in a range that fills a Short, or 16 bits, signed.

The conversion from the Short to bytes depends in part if you are big-endian or little-endian. Also you have to manage whether there are multiple tracks or not (e.g., stereo is common). All these steps have been covered in other Stackoverflow posts.

What you do with the data array once you have it, how it is combined with the existing audio, depends in part on whether you are outputting as audio or trying to create a new wav file to export. There are sections of the Java Tutorial's Audio Trail that cover playback, saving files, as well as a good section on file formats and format conversions (highly recommended you read this).

Phil Freihofner
  • 7,645
  • 1
  • 20
  • 41