Date: Fri, 20 Dec 2019 19:02:33 -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: <CAPe0dB=DF62Nq-h-mne8itZD-U6dTdhAqPrrV8g9OvHGGmooXg@mail.gmail.com> In-Reply-To: <77875a51-0cef-a27f-7d27-9eac8426bb74@selasky.org> References: <CAPe0dB=BGyeLX3Xue=nNpHqRn8s-4xAO_T4Asmv-DUGk8uu2Jg@mail.gmail.com> <77875a51-0cef-a27f-7d27-9eac8426bb74@selasky.org>
next in thread | previous in thread | raw e-mail | index | archive | help
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> #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; 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"); int *buf[fragmentSize]; read(fdDsp, buf, fragmentSize); write(fdOutput, buf, fragmentSize); } 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."); } int buf[fragmentSize]; eof = read(fdInput, buf, fragmentSize); //bytes read or -1 if EOF // audio processing: for(int i=0;i<fragmentSize;i++){ // learning how to get left and right channels from buffer int l = (buf)[i] & 0xffff; int r = ((buf)[i] >> 16) & 0xffff ; // FIXME: it is causing distortion: float fl = l; float fr = r; fl *= 1.0; fr *= 0.3; //if different than 1, sounds distorted and noisy l = fl; r = fr; // OK: unite Left and Right channels again int lr = (l ) | (r << 16); // OK: other options to mix these two channels: int lleft = l; //Just the left channel int rright = (r << 16); //Just the right channel int lmono = (l << 16) | l; //Left ch. on both channels int rmono = (r << 16) | r; //Right ch. on both channels // the output: (buf)[i] = lr; } 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? > --HPS >
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAPe0dB=DF62Nq-h-mne8itZD-U6dTdhAqPrrV8g9OvHGGmooXg>