Date: Sat, 21 Dec 2019 01:54:24 -0300 From: Marcel Bonnet <marcelbonnet@gmail.com> To: Hans Petter Selasky <hps@selasky.org> Cc: FreeBSD multimedia <freebsd-multimedia@freebsd.org> Subject: Re: [off-topic] Applying gain to an audio sample Message-ID: <CAPe0dBmQkpTroA5=E865xTUxdH6K-HNbmrmG_7vJXo-kYsBJKA@mail.gmail.com> In-Reply-To: <7639f4fe-f021-bfca-13a7-f4d529aa3080@selasky.org> 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> <7639f4fe-f021-bfca-13a7-f4d529aa3080@selasky.org>
next in thread | previous in thread | raw e-mail | index | archive | help
On Fri, 20 Dec 2019 at 19:43, Hans Petter Selasky <hps@selasky.org> wrote: > 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 > Thank you! As you pointed out, I was using the wrong type for my buffer and also the wrong number for nbytes in read()/write() . I updated the code with other changes needed. Now gain factor works perfectly as observed in SoX source code I previously mentioned. Updated Code: #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> //has type int16_t (short) #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/stereo.wav"; //Raw file to record and playback int fragmentSize = 256; int b_continue = 1; 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"); // Wrong: // int *buf[fragmentSize]; // read(fdDsp, buf, fragmentSize); // write(fdOutput, buf, fragmentSize); int16_t *buf[fragmentSize/sizeof (int16_t)]; read(fdDsp, buf, fragmentSize/sizeof (int16_t)); write(fdOutput, buf, fragmentSize/sizeof (int16_t)); } 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."); } //Wrong buffer type (too large) and wrong last parameter for read(): // int buf[fragmentSize]; // eof = read(fdInput, buf, fragmentSize); int16_t buf[fragmentSize/sizeof (int16_t)]; eof = read(fdInput, buf, fragmentSize/sizeof (int16_t)); // audio processing: for(int i=0;i<fragmentSize/sizeof (int16_t);i++){ int16_t l = buf[i]; int16_t r = buf[i+1]; // Using int16_t (short) buffer, gain works but stereo is inverted with factor >= 1.4f float fl = l; float fr = r; fl *= 2.0f; fr *= 3.0f; l = fl; r = fr; // the output: (buf)[i] = l; i++; (buf)[i] = r; } // write(fdDsp, buf, fragmentSize); //wrong write(fdDsp, buf, fragmentSize/sizeof (int16_t)); 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; } -- Marcel Bonnet
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAPe0dBmQkpTroA5=E865xTUxdH6K-HNbmrmG_7vJXo-kYsBJKA>