From owner-freebsd-multimedia@freebsd.org Sat Dec 21 04:54:51 2019 Return-Path: Delivered-To: freebsd-multimedia@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 404821EF4E4 for ; Sat, 21 Dec 2019 04:54:51 +0000 (UTC) (envelope-from marcelbonnet@gmail.com) Received: from mail-ot1-x343.google.com (mail-ot1-x343.google.com [IPv6:2607:f8b0:4864:20::343]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "smtp.gmail.com", Issuer "GTS CA 1O1" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 47ftZf4FSWz3Ndw for ; Sat, 21 Dec 2019 04:54:50 +0000 (UTC) (envelope-from marcelbonnet@gmail.com) Received: by mail-ot1-x343.google.com with SMTP id d7so10200950otf.5 for ; Fri, 20 Dec 2019 20:54:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=Yj7yLCh23oCoOZl8Fgmo72y+6MZnTEUgCuJWBjZSsbE=; b=QQxNlMb+H6BUek4sNWM6hcRXIIAVdlTswG0mSpyToFc8dbKA3DWaltNFhFdkrSyF5c mTAO2d7N03VaBx3dSKIM663aZwhPcekHr06e2xxv2MJ4Sjffd2rtVDQJyuRLBD6/iFWB tTieIbTDup56rnnlKgDcner9ix2i5Y958UpIEkWi4BUcn9WP5RN4HdY6bXpE4KGcyYTu UiqFz1OFHci+kPj5zsrN05rnm4dbVJ9oyofXCuIRoNxy0MeeRYGJtwHuj7tRAV/K99hV 7Cl19SddIE5+DMvgZ1fuhGav88gl9GvxEytsD4gh3RVKSvz+n/5OcrfRdE1T7jTOlcn4 wiBA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=Yj7yLCh23oCoOZl8Fgmo72y+6MZnTEUgCuJWBjZSsbE=; b=jofCM/ZHzC/5JGfSW+0RHYCeECEhzt6xMWLXNtdsruOIq43OpxQK5mN6TUVhZpgmbT gs3lTH6giu1tVx64NkREvKnWZeRiIXv9O+abldcEhKaKUN7lzB8IvbpKtvvvhk80B5KM /4pSItU8Oo3+tFyTuNSObVypb+Jx5OhMZWrGiL0Q6JVFXTBvcqRk3IzJZRlx+Nz6jvKt zGxgKyTZYJ437TQUCHiMXdTMpJM33yMzQYm0g3lW8cC+ThE5ETGHh+Ohjb6iAEiI722Y JTuMFP6V7sm45hdjpdjlcKHi3BhMZ8NdUoxMn1RVGbU/RWTyAPVhmrUx+niVhs/tddp9 pcVQ== X-Gm-Message-State: APjAAAU+zM7q8/6u3IRQ25QK/JFf3JMqD2pUBwIRAT4nOxki7wnzX8A1 08yYZjr+81p+wXyf7yVQ7y8xaO6tKA3NfOg32A4byhFI X-Google-Smtp-Source: APXvYqzhQ+Br289YOYa10k4UokyY+qSXKS96gpLsb1CSdUd0TUt8fHM5ykb/UI6mXaWfg77qshwthYwkLDk/HRjSMo8= X-Received: by 2002:a9d:3b09:: with SMTP id z9mr19259552otb.195.1576904089200; Fri, 20 Dec 2019 20:54:49 -0800 (PST) MIME-Version: 1.0 References: <77875a51-0cef-a27f-7d27-9eac8426bb74@selasky.org> <7639f4fe-f021-bfca-13a7-f4d529aa3080@selasky.org> In-Reply-To: <7639f4fe-f021-bfca-13a7-f4d529aa3080@selasky.org> From: Marcel Bonnet Date: Sat, 21 Dec 2019 01:54:24 -0300 Message-ID: Subject: Re: [off-topic] Applying gain to an audio sample To: Hans Petter Selasky Cc: FreeBSD multimedia X-Rspamd-Queue-Id: 47ftZf4FSWz3Ndw X-Spamd-Bar: -- Authentication-Results: mx1.freebsd.org; dkim=pass header.d=gmail.com header.s=20161025 header.b=QQxNlMb+; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (mx1.freebsd.org: domain of marcelbonnet@gmail.com designates 2607:f8b0:4864:20::343 as permitted sender) smtp.mailfrom=marcelbonnet@gmail.com X-Spamd-Result: default: False [-3.00 / 15.00]; ARC_NA(0.00)[]; NEURAL_HAM_MEDIUM(-1.00)[-1.000,0]; R_DKIM_ALLOW(-0.20)[gmail.com:s=20161025]; FROM_HAS_DN(0.00)[]; R_SPF_ALLOW(-0.20)[+ip6:2607:f8b0:4000::/36]; FREEMAIL_FROM(0.00)[gmail.com]; MIME_GOOD(-0.10)[multipart/alternative,text/plain]; PREVIOUSLY_DELIVERED(0.00)[freebsd-multimedia@freebsd.org]; NEURAL_HAM_LONG(-1.00)[-1.000,0]; IP_SCORE_FREEMAIL(0.00)[]; TO_MATCH_ENVRCPT_SOME(0.00)[]; TO_DN_ALL(0.00)[]; DKIM_TRACE(0.00)[gmail.com:+]; RCPT_COUNT_TWO(0.00)[2]; RCVD_IN_DNSWL_NONE(0.00)[3.4.3.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.4.6.8.4.0.b.8.f.7.0.6.2.list.dnswl.org : 127.0.5.0]; DMARC_POLICY_ALLOW(-0.50)[gmail.com,none]; IP_SCORE(0.00)[ip: (2.84), ipnet: 2607:f8b0::/32(-2.18), asn: 15169(-1.89), country: US(-0.05)]; FROM_EQ_ENVFROM(0.00)[]; MIME_TRACE(0.00)[0:+,1:+,2:~]; FREEMAIL_ENVFROM(0.00)[gmail.com]; ASN(0.00)[asn:15169, ipnet:2607:f8b0::/32, country:US]; RCVD_COUNT_TWO(0.00)[2]; RCVD_TLS_ALL(0.00)[]; DWL_DNSWL_NONE(0.00)[gmail.com.dwl.dnswl.org : 127.0.5.0] Content-Type: text/plain; charset="UTF-8" X-Content-Filtered-By: Mailman/MimeDel 2.1.29 X-BeenThere: freebsd-multimedia@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Multimedia discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 21 Dec 2019 04:54:51 -0000 On Fri, 20 Dec 2019 at 19:43, Hans Petter Selasky wrote: > On 2019-12-20 23:02, Marcel Bonnet wrote: > > Em sex, 20 de dez de 2019 15:46, Hans Petter Selasky > > 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 > > #include > > #include > > #include "/usr/include/sys/soundcard.h" > > #include > > #include > > #include //man 2 chmod > > #include > > #include > > > > > #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 #include #include #include "/usr/include/sys/soundcard.h" #include #include #include //man 2 chmod #include #include //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= 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