5
\$\begingroup\$

I have generated a synthetic 'concert pitch A' tone from sinewaves.

It plays properly on OS X player, and on my Android device.

Now I record myself singing a 'concert pitch A' into the microphone as a MONO .WAV -- foo.wav.

In Unity I add foo.wav to my resources, making sure to turn off "is 3D sound" in the settings panel.

I then create a script that loads it into an audioclip and extracts the contents into a float buffer:

    AudioSettings.outputSampleRate = 44100; // just to be safe

    AudioClip phonemeClip = Resources.Load( filename ) as AudioClip;

    float [] phonemeBuf = new float[ phonemeClip.samples * phonemeClip.channels ];

    phonemeClip.GetData( phonemeBuf, 0 );

I then add this sound to my synthetic tone, 30000 samples in (so nearly 1 second):

    float PHONEME_VOL = 0.3f;
    int OFFSET = 30000;

    for(int i=0; i<phonemeBuf.Length; i++) 
        if( OFFSET+i < buf.Length )
            buf[OFFSET+i] += phonemeBuf[i] * PHONEME_VOL;

On OSX player this works perfectly.

However on my android device the original synthetic tone plays correctly whereas the added foo.wav appears to be exactly an octave low.

What might be causing this?

I suspect it may be converting the clip into a stereo clip, with 0 for the right channel. That would interpolate the resultant float buffer with zeros, which would certainly take it down octave.

But I can't see how to address this problem.

\$\endgroup\$
  • 1
    \$\begingroup\$ Do you know the default outputSampleRate, did you try other values ? jarcas.com/studios/?p=188 3) says increasing it made the song play slower. \$\endgroup\$ – Heckel May 16 '14 at 13:34
1
\$\begingroup\$

The output rate on Android could be locked to 22Khz or depend on the devices. In this case you will have to adjust the mixing rate in software:

//        foo.wav speed * 8bits of fractions / outputSampleRate
int speed = 44100 * 256 / AudioSettings.outputSampleRate;
for(int i=0,j=0,max=phonemeBuf.Length * 256; j<max; ++i, j+=speed) 
    if( OFFSET+i < buf.Length )
        buf[OFFSET+i] += phonemeBuf[j >> 8] * PHONEME_VOL;

Or it could have been converted to stereo. try:

int c = phonemeClip.channels;
for(int i=0, j=0, max=phonemeBuf.Length; j<max; ++i, j+=c) 
    if( OFFSET+i < buf.Length )
        buf[OFFSET+i] += phonemeBuf[j] * PHONEME_VOL;

ideally, combine both sample-rate conversion and mixing only the left channel.

int c = phonemeClip.channels;
int speed = 44100 * 256 / AudioSettings.outputSampleRate;
for(int i=0,j=0,max=phonemeBuf.Length * 256; j<max; ++i, j+=speed) 
    if( OFFSET+i < buf.Length )
        buf[OFFSET+i] += phonemeBuf[(j >> 8)*c] * PHONEME_VOL;
| improve this answer | |
\$\endgroup\$

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.