Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 20 Dec 2019 23:42:14 +0100
From:      Hans Petter Selasky <hps@selasky.org>
To:        Marcel Bonnet <marcelbonnet@gmail.com>
Cc:        FreeBSD multimedia <freebsd-multimedia@freebsd.org>
Subject:   Re: [off-topic] Applying gain to an audio sample
Message-ID:  <7639f4fe-f021-bfca-13a7-f4d529aa3080@selasky.org>
In-Reply-To: <CAPe0dB=DF62Nq-h-mne8itZD-U6dTdhAqPrrV8g9OvHGGmooXg@mail.gmail.com>
References:  <CAPe0dB=BGyeLX3Xue=nNpHqRn8s-4xAO_T4Asmv-DUGk8uu2Jg@mail.gmail.com> <77875a51-0cef-a27f-7d27-9eac8426bb74@selasky.org> <CAPe0dB=DF62Nq-h-mne8itZD-U6dTdhAqPrrV8g9OvHGGmooXg@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On 2019-12-20 23:02, Marcel Bonnet wrote:
> Em sex, 20 de dez de 2019 15:46, Hans Petter Selasky <hps@selasky.org>
> escreveu:
> 
>> On 2019-12-20 19:43, Marcel Bonnet wrote:
>>> - read an audio sample as integer (stereo 16 bit LE)
>>> - convert to float
>>> - apply a gain, like: sample *= 0.3f
>>> - convert to integer again
>>
>> The attachment is missing.
>>
> 
> Sorry, here it is.
> 
> #include <stdio.h>
> #include <unistd.h>
> #include <fcntl.h>
> #include "/usr/include/sys/soundcard.h"
> #include <sys/ioctl.h>
> #include <sys/time.h>
> #include <sys/stat.h> //man 2 chmod
> #include <signal.h>

#include <stdint.h>

> 
> #define DEBUG 1
> #define log(msg) if (DEBUG) printf("[LOG] %s\n",msg)
> #define err(msg)  {printf("[ERR] %s\n",msg); exit(1); }
> 
> 
> const char *device = "/dev/dsp3.1";     //Audio device
> char *rawFile = "/tmp/raw-file.wav";    //Raw file to record and playback
> int fragmentSize = 256;
> int b_continue = 1;

Look here:

> 
> 
> void signalHandler(int sigNum){
>      log("Signal captured");
>      b_continue = 0;
> }
> 
> 
> void configDevice(int fdDsp){
>      int ossCapabilities = 0;
> 
>      if(fdDsp == -1)
>          err("can't open device");
> 
>      if( ioctl(fdDsp, SNDCTL_DSP_GETCAPS, &ossCapabilities) == -1)
>          err("unsupported: SNDCTL_DSP_GETCAPS");
> 
>      /*
>       * http://www.opensound.com/pguide/audio2.html
>       */
> 
>      if(ossCapabilities & DSP_CAP_TRIGGER != DSP_CAP_TRIGGER){
>          err("Triggering of recording/playback is not possible with
> this OSS device.");
> 
>      }
> 
>      if(ossCapabilities & DSP_CAP_REALTIME != DSP_CAP_REALTIME){
>          err("No DSP_CAP_REALTIME.");
> 
>      }
> 
>      if(ioctl(fdDsp, SNDCTL_DSP_SETDUPLEX, &ossCapabilities) == -1)
>          err("can't SNDCTL_DSP_SETDUPLEX");
> 
>      if(ossCapabilities & DSP_CAP_DUPLEX != DSP_CAP_DUPLEX)
>          err("can't DSP_CAP_DUPLEX");
> 
>      int format = AFMT_S16_LE;   //set format
>      if(ioctl(fdDsp, SNDCTL_DSP_SETFMT, &format ) == -1){
>          err("Error setting format.");
> 
>      }
> 
>      int channels = 1; //mono=0 stereo=1
>      if(ioctl(fdDsp, SNDCTL_DSP_STEREO, &channels ) == -1){
>          err("Error setting channels." );
> 
>      }
>      // FREQUENCY RATE
>      int speed = 44100;
>      if(ioctl(fdDsp, SNDCTL_DSP_SPEED, &speed ) == -1){
>          err("Error setting speed.");
> 
>      }
> 
>      // FRAGMENT SIZE
>      if(ioctl(fdDsp, SNDCTL_DSP_SETBLKSIZE, &fragmentSize) == -1){
> //normalmente 2048 bits
>          err("Cannot SNDCTL_DSP_SETBLKSIZE.");
> 
>      }
> 
> 
> }
> 
> void record(){
>      int fdDsp = open(device, O_RDONLY);
>      configDevice(fdDsp);
>      //create file for writing
>      const int fdOutput = open(rawFile, O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR);
> 
>      if(fdOutput ==-1)
>          err("can't open file to write");
>      log("Recording...");
> 
>      do{
>           // Triggers recording
>           int enableBits = PCM_ENABLE_INPUT;
>           if(ioctl(fdDsp, SNDCTL_DSP_SETTRIGGER, &enableBits) == -1)
>               err("Can't record: SNDCTL_DSP_SETTRIGGER");
> 

This buffer declaration is wrong.

>           int *buf[fragmentSize];

Use:
	    int16_t buf[fragmentSize / sizeof(int16_t)];

>           read(fdDsp, buf, sizeof(buf));
>           write(fdOutput, buf, sizeof(buf));
> 
>       } while(b_continue == 1);
> 
>       close(fdOutput);
>       close(fdDsp);
> }
> 
> void playback(){
>      log("Opening file:");
>      log(rawFile);
>      log("On device:");
>      log(device);
> 
>      int fdDsp = open(device, O_WRONLY);
>      configDevice(fdDsp);
> 
>      const int fdInput = open(rawFile, O_RDONLY);
> 
>      if(fdInput ==-1)
>          err("can't open file");
>      log("Playing...");
> 
>      int eof = 0;
> 
>      do{
>          // TRIGGERs PLAYBACK
>          int enableBits = PCM_ENABLE_OUTPUT;
>          if(ioctl(fdDsp, SNDCTL_DSP_SETTRIGGER, &enableBits) == -1){
>              err("Cannot SNDCTL_DSP_SETTRIGGER.");
> 
>          }
> 
Ditto:
           int16_t buf[fragmentSize / sizeof(int16_t)];

>          eof = read(fdInput, buf, sizeof(buf)); //bytes read or -1 if EOF
> 
>          // audio processing:
>          for(int i=0;i < fragmentSize;i++){
		float sample = buf[i];

		sample *= 0.3;
		buf[i] = sample;
>          }
> 
>          write(fdDsp, buf, fragmentSize);
>          if(b_continue == 0) break;
>      } while(eof > 0);
> 
>      close(fdInput);
>      close(fdDsp);
> }
> 
> int main(int argc, char *argv[])
> {
> 
>      signal(SIGINT, signalHandler);
>      log("Ctrl^C to stop recording/playback");
>      record();
>      b_continue = 1; playback();
>      log("Stopped.");
>      return 0;
> }
> 
> 
> 
> 
>> Probably better to use the host endian version of AFMT
> 
> 
> You mean AFMT_S16_NE ? The native endian?

Yes.

Try my corrections first.

--HPS



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?7639f4fe-f021-bfca-13a7-f4d529aa3080>