[off-topic] Applying gain to an audio sample
Hans Petter Selasky
hps at selasky.org
Fri Dec 20 22:43:19 UTC 2019
On 2019-12-20 23:02, Marcel Bonnet wrote:
> Em sex, 20 de dez de 2019 15:46, Hans Petter Selasky <hps at 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
More information about the freebsd-multimedia
mailing list