Mono recording issues

Discussion about writing software for VS1005 and the VSOS Operating System. Also posts about VS1005-related hardware design and device drivers should be posted here.
Post Reply
RLee
Senior User
Posts: 30
Joined: Wed 2017-11-22 13:43

Mono recording issues

Post by RLee »

Hello,

Appologies if this is obvious, but it isn't to me and i cannot find it here or in the manuals.

I am trying to write to a mono, 24 bit, 96 kHz wav file. Stereo works absolutely fine.

When recording the file is the correct size, length and the header looks good. However, what has happened is 5 seconds of audio has been stretched out to 10 seconds. There is some mirroring when the wav is viewed as a spectrogram
2025-02-14 16_12_51-Window.png
2025-02-14 16_12_51-Window.png (85.9 KiB) Viewed 4726 times
when viewed as a waveform there is clear alternating between samples between two channels.
2025-02-14 16_14_43-Window.png
2025-02-14 16_14_43-Window.png (5.28 KiB) Viewed 4726 times
my header looks like this.

Code: Select all

s_int16 SetRiff(s_int32 sampleRate, s_int32 stereoSamples)  {
	s_int32 fileBytes = 44+(CHANS*(BITR/8)*stereoSamples); // Stereo=2, 16 bits=2 **44+2*2*stereoSamples
	SetLE32(riffWavHeader, RIFF_SAMPLE_RATE_OFFSET,SRATE);
	SetLE16(riffWavHeader, RIFF_NUMBER_OF_CHANNELS_OFFSET, CHANS);
	SetLE32(riffWavHeader, RIFF_BYTES_PER_SEC_OFFSET,   CHAN*(BITR/8)*SRATE);//2*2*sampleRate)
	SetLE16(riffWavHeader, RIFF_ALIGN_OFFSET,CHANS*BITR/8);///was 24/4
	SetLE16(riffWavHeader, RIFF_BITS_PER_SAMPLE_OFFSET, BITR);
	SetLE32(riffWavHeader, RIFF_FILE_SIZE_OFFSET, fileBytes- 8);
	SetLE32(riffWavHeader, RIFF_DATA_SIZE_OFFSET, fileBytes-44);
  return 0;
}
and fread/fwrite like this

Code: Select all

  // Configure standard audio input 
 ioctl(stdaudioin, IOCTL_AUDIO_SET_IRATE, (void *)(&sampleRate));
 ioctl(stdaudioin, IOCTL_AUDIO_SET_BITS, (void *)ModBit);
// ioctl(stdaudioin, IOCTL_AUDIO_SET_RATE_AND_BITS,(void *)(&sampleRateAndBits));//just added
ioctl(stdaudioin, IOCTL_AUDIO_GET_OVERFLOWS, (void *)(&overflows));
  if (ioctl(stdaudioin, IOCTL_AUDIO_SET_INPUT_BUFFER_SIZE, (void *)4096)) {
    printf("Couldn't set input biffer size\n");
    goto finally;
  }
 
  SetRiff(sampleRate, samplesLeft/CHANS);//this was samplesLeft/2 which was shortenting this for single channels
  samplesLeft = (samplesLeft*(ModBit/16));
 fwrite(&riffWavHeader, sizeof(riffWavHeader), 1, outFile);

  while (samplesLeft) {
   s_int16 i;
    s_int16 samples = (s_int16)MIN(samplesLeft, BUFSIZE);
       u_int16*bp = buff16;
        
    fread(buff16, sizeof(buff16[0]), samples, stdaudioin);
	 if (bitR==24) {

  Convert32BitVSDSPTo24BitLE(buff16, (u_int32 *)buff16, samples/4); // 256-word buffer contains 64 32-bit stereo samples ***was samples divided by 4 
  fwrite(buff16, sizeof(buff16[0]), samples*3/4, outFile); // Write 32-bit little-endian data */
} else {
for (i=0; i<samples; i++) {
      *bp = Swap16(*bp);
      bp++;
    }
  fwrite(buff16, sizeof(buff16[0]), samples, outFile);
	
}
I have a feeling it is either in the Convert32BitVSDSPTo24BitLE function or stdaudioin, but after good 2 days i have given up trying to find the source. As I said stereo works perfectly.

Also the config file is AUIADC s 96000 line1_3

Thanks in advance

Rob
User avatar
pasi
VLSI Staff
Posts: 2174
Joined: Thu 2010-07-15 16:04

Re: Mono recording issues

Post by pasi »

It looks like you're writing a mono WAV header, but the data remains stereo. Thus, every other sample is from the left and every other from the right channel, producing a double-length file.

Don't you need to switch the stdoudioin to mono first?
Visit https://www.facebook.com/VLSISolution VLSI Solution on Facebook
RLee
Senior User
Posts: 30
Joined: Wed 2017-11-22 13:43

Re: Mono recording issues

Post by RLee »

Thanks for the reply,

i added this line which did nothing so assumed I was wrong.

Code: Select all

ioctl(stdaudioin, IOCTL_AUDIO_SELECT_INPUT,(void *)(AID_LINE1_3));
Thanks Rob
User avatar
pasi
VLSI Staff
Posts: 2174
Joined: Thu 2010-07-15 16:04

Re: Mono recording issues

Post by pasi »

I know next to nothing about VSOS, but would ioctl(stdaudioin, IOCTL_AUDIO_SET_ICHANNELS, 1); do it?

or

AUIADC m 96000 line1_3
Visit https://www.facebook.com/VLSISolution VLSI Solution on Facebook
RLee
Senior User
Posts: 30
Joined: Wed 2017-11-22 13:43

Re: Mono recording issues

Post by RLee »

unfortunately not.

nor does ioctl(stdaudioin, IOCTL_AUDIO_SET_MONO,(void *)(MONO_MODE_MONO))

I am truly baffled now.

Another option might be to strip every alternate sample from stdaudioin, however this feels like a massive bodge. I am sure I am missing something obvious. If you have any other ideas please advise, but I will write the solution if i somehow find it.

Thanks again
Hannu
VLSI Staff
Posts: 561
Joined: Mon 2016-05-30 11:54
Location: Finland
Contact:

Re: Mono recording issues

Post by Hannu »

VSOS_Audio.pdf wrote: IOCTL_AUDIO_SET_ICHANNELS, IOCTL_AUDIO_SET_OCHANNELS
Set number of bits audio channels. As of the writing of this (2023-02-28) no drivers
support this function.
Example for input driver:
if (ioctl(fp, IOCTL_AUDIO_SET_ICHANNELS, (char *)(6))) {
printf("Couldn’t set number of channels\n");
I would do something like this, or memcopystride() or try to win the compiler with my own assembly routine.

Code: Select all

#define BUFFER_SAMPLES 128
#define BUFFER_SIZE (BUFFER_SAMPLES * 2 * 2)
s_int16 buffer[BUFFER_SIZE];

void SimpleCopyNotTestedOrNotEvenCompiled() {
	s_int32 *s = buffer, *d = buffer;
	u_int16 i;
	d++; /* first right */
	s += 2; /* second left */
	fread(buffer, BUFFER_SAMPLES, 4, stdaudioin);
	for (i = 0;i < BUFFER_SAMPLES; i++) {
		*d++ = *s;
		s += 2;
	}
	Convert32BitVSDSPTo24BitLE(buffer, (u_int32 *)buffer,
				   BUFFER_SAMPLES / 2); /* Rights removed */
	fwrite(buffer, BUFFER_SAMPLES / 2, 4, fp);
}
RLee
Senior User
Posts: 30
Joined: Wed 2017-11-22 13:43

Re: Mono recording issues

Post by RLee »

OK I have implemented this and it works great. There was a little adjusting needed so i put that below for any others using this as a reference. It did halve the length of the recording but this was obviously a really easy fix.

I did have an issue where I needed to select the right channel, this put an extra sample in, which i assume is an anomaly from a sample being carried forward for form the for loop. But by adding the SetMono driver and swapping the channels this seems to have been fixed.

Thanks again for all your help.

Code: Select all


#define BUFFER_SAMPLES 64
#define BUFSIZE (BUFFER_SAMPLES * 2 * 2)
u_int16 buff16[BUFSIZE];


{
s_int32 *s = buff16, *d = buff16;
u_int16 i;
d++; /* first right */
s += 2; /* second left */
fread(buff16, BUFFER_SAMPLES, 4, stdaudioin);
	for (i = 0; i < BUFFER_SAMPLES; i++) {
	*d++ = *s; ///copy left
	s += 2;
	}
Convert32BitVSDSPTo24BitLE(buff16, (u_int32 *)buff16, BUFFER_SAMPLES/2); 
fwrite(buff16,BUFFER_SAMPLES/2,3,  outFile);
}

T
Hannu
VLSI Staff
Posts: 561
Joined: Mon 2016-05-30 11:54
Location: Finland
Contact:

Re: Mono recording issues

Post by Hannu »

RLee wrote: Tue 2025-02-18 13:31 OK I have implemented this and it works great. There was a little adjusting needed so i put that below for any others using this as a reference. It did halve the length of the recording but this was obviously a really easy fix.

I did have an issue where I needed to select the right channel, this put an extra sample in, which i assume is an anomaly from a sample being carried forward for form the for loop. But by adding the SetMono driver and swapping the channels this seems to have been fixed.
Actually I thought about this yesterday how to implement this to mono driver, but it is rather tricky thing to do. Not impossible.

Taking the right channel is just a matter of the initialization:

Code: Select all

s = d = (s_int32 *)buffer;
s++; /* s is first right  and d stays in first left */
There is a requirement: The read sample count must be dividable by 4.
If we have L1R1L2R2 samples and then we take for example left and get L1L2 which can be fed to Convert....() which expects stereo samples.

I took your code and added some comments about the magic numbers. Hopefully they are correct and I didn't make any mistakes. I tried to be careful.

Code: Select all

#define BUFFER_SAMPLES 64
#define BUFSIZE (BUFFER_SAMPLES * 2 * 2)
u_int16 buff16[BUFSIZE];


{
s_int32 *s = buff16, *d = buff16;
u_int16 i;
d++; /* first right */
s += 2; /* second left */
fread(buff16, BUFFER_SAMPLES, 4, stdaudioin); /* Magic 4: 2 channels * 2 words (32-bit) */
	for (i = 0; i < BUFFER_SAMPLES; i++) {
		*d++ = *s; ///copy left
		s += 2;
	}
	/* There are still BUFFER_SAMPLES elements. Only half of the magic 4 was removed.
	 * However Convert...() expects to receive stereo samples */
	Convert32BitVSDSPTo24BitLE(buff16, (u_int32 *)buff16, BUFFER_SAMPLES / 2); 
	/* Every sample takes 1.5 words 3 / 2 fraction comes from that */
	fwrite(buff16,BUFFER_SAMPLES / 2, 3,  outFile);
}

[/quote]
Post Reply