1bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian/* 2bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian * Copyright (C) 2012 The Android Open Source Project 3bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian * 4bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian * Licensed under the Apache License, Version 2.0 (the "License"); 5bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian * you may not use this file except in compliance with the License. 6bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian * You may obtain a copy of the License at 7bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian * 8bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian * http://www.apache.org/licenses/LICENSE-2.0 9bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian * 10bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian * Unless required by applicable law or agreed to in writing, software 11bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian * distributed under the License is distributed on an "AS IS" BASIS, 12bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian * See the License for the specific language governing permissions and 14bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian * limitations under the License. 15bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian */ 16bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian 17bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian#include "AudioResampler.h" 18bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian#include <media/AudioBufferProvider.h> 19bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian#include <unistd.h> 20bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian#include <stdio.h> 21bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian#include <stdlib.h> 22bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian#include <fcntl.h> 23bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian#include <string.h> 24bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian#include <sys/mman.h> 25bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian#include <sys/stat.h> 26bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian#include <errno.h> 27bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian#include <time.h> 287df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian#include <math.h> 29bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian 30bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopianusing namespace android; 31bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian 32bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopianstruct HeaderWav { 33bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian HeaderWav(size_t size, int nc, int sr, int bits) { 34bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian strncpy(RIFF, "RIFF", 4); 35bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian chunkSize = size + sizeof(HeaderWav); 36bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian strncpy(WAVE, "WAVE", 4); 37bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian strncpy(fmt, "fmt ", 4); 38bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian fmtSize = 16; 39bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian audioFormat = 1; 40bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian numChannels = nc; 41bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian samplesRate = sr; 42bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian byteRate = sr * numChannels * (bits/8); 43bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian align = nc*(bits/8); 44bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian bitsPerSample = bits; 45bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian strncpy(data, "data", 4); 46bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian dataSize = size; 47bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian } 48bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian 49bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian char RIFF[4]; // RIFF 50bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian uint32_t chunkSize; // File size 51bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian char WAVE[4]; // WAVE 52bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian char fmt[4]; // fmt\0 53bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian uint32_t fmtSize; // fmt size 54bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian uint16_t audioFormat; // 1=PCM 55bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian uint16_t numChannels; // num channels 56bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian uint32_t samplesRate; // sample rate in hz 57bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian uint32_t byteRate; // Bps 58bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian uint16_t align; // 2=16-bit mono, 4=16-bit stereo 59bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian uint16_t bitsPerSample; // bits per sample 60bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian char data[4]; // "data" 61bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian uint32_t dataSize; // size 62bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian}; 63bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian 64bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopianstatic int usage(const char* name) { 657df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian fprintf(stderr,"Usage: %s [-p] [-h] [-s] [-q {dq|lq|mq|hq|vhq}] [-i input-sample-rate] " 667df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian "[-o output-sample-rate] [<input-file>] <output-file>\n", name); 677df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian fprintf(stderr," -p enable profiling\n"); 687df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian fprintf(stderr," -h create wav file\n"); 697df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian fprintf(stderr," -s stereo\n"); 707df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian fprintf(stderr," -q resampler quality\n"); 717df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian fprintf(stderr," dq : default quality\n"); 727df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian fprintf(stderr," lq : low quality\n"); 737df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian fprintf(stderr," mq : medium quality\n"); 747df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian fprintf(stderr," hq : high quality\n"); 757df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian fprintf(stderr," vhq : very high quality\n"); 767df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian fprintf(stderr," -i input file sample rate\n"); 777df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian fprintf(stderr," -o output file sample rate\n"); 78bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian return -1; 79bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian} 80bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian 81bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopianint main(int argc, char* argv[]) { 82bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian 837df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian const char* const progname = argv[0]; 84bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian bool profiling = false; 85bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian bool writeHeader = false; 867df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian int channels = 1; 87bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian int input_freq = 0; 88bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian int output_freq = 0; 89bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian AudioResampler::src_quality quality = AudioResampler::DEFAULT_QUALITY; 90bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian 91bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian int ch; 927df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian while ((ch = getopt(argc, argv, "phsq:i:o:")) != -1) { 93bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian switch (ch) { 94bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian case 'p': 95bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian profiling = true; 96bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian break; 97bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian case 'h': 98bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian writeHeader = true; 99bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian break; 1007df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian case 's': 1017df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian channels = 2; 1027df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian break; 103bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian case 'q': 104bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian if (!strcmp(optarg, "dq")) 105bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian quality = AudioResampler::DEFAULT_QUALITY; 106bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian else if (!strcmp(optarg, "lq")) 107bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian quality = AudioResampler::LOW_QUALITY; 108bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian else if (!strcmp(optarg, "mq")) 109bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian quality = AudioResampler::MED_QUALITY; 110bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian else if (!strcmp(optarg, "hq")) 111bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian quality = AudioResampler::HIGH_QUALITY; 112bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian else if (!strcmp(optarg, "vhq")) 113bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian quality = AudioResampler::VERY_HIGH_QUALITY; 114bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian else { 1157df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian usage(progname); 116bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian return -1; 117bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian } 118bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian break; 119bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian case 'i': 120bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian input_freq = atoi(optarg); 121bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian break; 122bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian case 'o': 123bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian output_freq = atoi(optarg); 124bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian break; 125bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian case '?': 126bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian default: 1277df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian usage(progname); 128bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian return -1; 129bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian } 130bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian } 131bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian argc -= optind; 1327df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian argv += optind; 133bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian 1347df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian const char* file_in = NULL; 1357df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian const char* file_out = NULL; 1367df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian if (argc == 1) { 1377df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian file_out = argv[0]; 1387df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian } else if (argc == 2) { 1397df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian file_in = argv[0]; 1407df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian file_out = argv[1]; 1417df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian } else { 1427df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian usage(progname); 143bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian return -1; 144bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian } 145bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian 146bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian // ---------------------------------------------------------- 147bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian 1487df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian size_t input_size; 1497df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian void* input_vaddr; 1507df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian if (argc == 2) { 1517df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian struct stat st; 1527df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian if (stat(file_in, &st) < 0) { 1537df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian fprintf(stderr, "stat: %s\n", strerror(errno)); 1547df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian return -1; 1557df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian } 156bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian 1577df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian int input_fd = open(file_in, O_RDONLY); 1587df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian if (input_fd < 0) { 1597df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian fprintf(stderr, "open: %s\n", strerror(errno)); 1607df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian return -1; 1617df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian } 162bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian 1637df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian input_size = st.st_size; 1647df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian input_vaddr = mmap(0, input_size, PROT_READ, MAP_PRIVATE, input_fd, 0); 1657df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian if (input_vaddr == MAP_FAILED ) { 1667df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian fprintf(stderr, "mmap: %s\n", strerror(errno)); 1677df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian return -1; 1687df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian } 1697df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian } else { 1707df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian double k = 1000; // Hz / s 1717df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian double time = (input_freq / 2) / k; 1727df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian size_t input_frames = size_t(input_freq * time); 1737df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian input_size = channels * sizeof(int16_t) * input_frames; 1747df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian input_vaddr = malloc(input_size); 1757df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian int16_t* in = (int16_t*)input_vaddr; 1767df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian for (size_t i=0 ; i<input_frames ; i++) { 1777df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian double t = double(i) / input_freq; 1787df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian double y = sin(M_PI * k * t * t); 1797df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian int16_t yi = floor(y * 32767.0 + 0.5); 18098d9922247ef21b0faf8c7d817650b8327052a4aGlenn Kasten for (size_t j=0 ; j<(size_t)channels ; j++) { 181c6ccbabd2800e749bc86a34d2ae233f99102ba51Mathias Agopian in[i*channels + j] = yi / (1+j); 1827df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian } 1837df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian } 184bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian } 185bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian 186bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian // ---------------------------------------------------------- 187bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian 188bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian class Provider: public AudioBufferProvider { 189bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian int16_t* mAddr; 190bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian size_t mNumFrames; 191bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian public: 1927df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian Provider(const void* addr, size_t size, int channels) { 193bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian mAddr = (int16_t*) addr; 1947df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian mNumFrames = size / (channels*sizeof(int16_t)); 195bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian } 196bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian virtual status_t getNextBuffer(Buffer* buffer, 197bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian int64_t pts = kInvalidPTS) { 198bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian buffer->frameCount = mNumFrames; 199bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian buffer->i16 = mAddr; 200bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian return NO_ERROR; 201bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian } 202bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian virtual void releaseBuffer(Buffer* buffer) { 203bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian } 2047df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian } provider(input_vaddr, input_size, channels); 205bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian 2067df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian size_t input_frames = input_size / (channels * sizeof(int16_t)); 2077df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian size_t output_size = 2 * 4 * ((int64_t) input_frames * output_freq) / input_freq; 208bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian output_size &= ~7; // always stereo, 32-bits 209bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian 210bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian void* output_vaddr = malloc(output_size); 211bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian 2127df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian if (profiling) { 2137df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian AudioResampler* resampler = AudioResampler::create(16, channels, 2147df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian output_freq, quality); 215bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian 2167df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian size_t out_frames = output_size/8; 2177df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian resampler->setSampleRate(input_freq); 2187df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian resampler->setVolume(0x1000, 0x1000); 219bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian 220bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian memset(output_vaddr, 0, output_size); 221bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian timespec start, end; 222bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian clock_gettime(CLOCK_MONOTONIC_HR, &start); 223bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian resampler->resample((int*) output_vaddr, out_frames, &provider); 2247df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian resampler->resample((int*) output_vaddr, out_frames, &provider); 2257df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian resampler->resample((int*) output_vaddr, out_frames, &provider); 2267df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian resampler->resample((int*) output_vaddr, out_frames, &provider); 227bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian clock_gettime(CLOCK_MONOTONIC_HR, &end); 228bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian int64_t start_ns = start.tv_sec * 1000000000LL + start.tv_nsec; 229bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian int64_t end_ns = end.tv_sec * 1000000000LL + end.tv_nsec; 2307df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian int64_t time = (end_ns - start_ns)/4; 231bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian printf("%f Mspl/s\n", out_frames/(time/1e9)/1e6); 2327df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian 2337df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian delete resampler; 234bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian } 235bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian 2367df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian AudioResampler* resampler = AudioResampler::create(16, channels, 2377df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian output_freq, quality); 2387df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian size_t out_frames = output_size/8; 2397df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian resampler->setSampleRate(input_freq); 2407df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian resampler->setVolume(0x1000, 0x1000); 2417df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian 2427df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian memset(output_vaddr, 0, output_size); 2437df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian resampler->resample((int*) output_vaddr, out_frames, &provider); 2447df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian 245bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian // down-mix (we just truncate and keep the left channel) 246bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian int32_t* out = (int32_t*) output_vaddr; 2477df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian int16_t* convert = (int16_t*) malloc(out_frames * channels * sizeof(int16_t)); 248bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian for (size_t i = 0; i < out_frames; i++) { 2497df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian for (int j=0 ; j<channels ; j++) { 2507df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian int32_t s = out[i * 2 + j] >> 12; 2517df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian if (s > 32767) s = 32767; 2527df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian else if (s < -32768) s = -32768; 2537df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian convert[i * channels + j] = int16_t(s); 2547df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian } 255bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian } 256bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian 257bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian // write output to disk 2587df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian int output_fd = open(file_out, O_WRONLY | O_CREAT | O_TRUNC, 259bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 260bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian if (output_fd < 0) { 261bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian fprintf(stderr, "open: %s\n", strerror(errno)); 262bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian return -1; 263bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian } 264bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian 265bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian if (writeHeader) { 2667df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian HeaderWav wav(out_frames * channels * sizeof(int16_t), channels, output_freq, 16); 267bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian write(output_fd, &wav, sizeof(wav)); 268bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian } 269bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian 2707df17073f1783421d6ed2013e6b55c60283d1474Mathias Agopian write(output_fd, convert, out_frames * channels * sizeof(int16_t)); 271bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian close(output_fd); 272bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian 273bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian return 0; 274bcf5220780fbf24477bf8d6148581307356c97b7Mathias Agopian} 275