19bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten/* 29bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten * Copyright (C) 2012 The Android Open Source Project 39bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten * 49bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten * Licensed under the Apache License, Version 2.0 (the "License"); 59bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten * you may not use this file except in compliance with the License. 69bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten * You may obtain a copy of the License at 79bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten * 89bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten * http://www.apache.org/licenses/LICENSE-2.0 99bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten * 109bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten * Unless required by applicable law or agreed to in writing, software 119bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten * distributed under the License is distributed on an "AS IS" BASIS, 129bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten * See the License for the specific language governing permissions and 149bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten * limitations under the License. 159bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten */ 169bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten 179bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten#include "AudioResampler.h" 189bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten#include <media/AudioBufferProvider.h> 199bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten#include <unistd.h> 209bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten#include <stdio.h> 219bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten#include <stdlib.h> 229bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten#include <fcntl.h> 239bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten#include <string.h> 249bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten#include <sys/mman.h> 259bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten#include <sys/stat.h> 269bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten#include <errno.h> 279bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten#include <time.h> 289bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten#include <math.h> 299bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten 309bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kastenusing namespace android; 319bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten 329bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kastenstruct HeaderWav { 339bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten HeaderWav(size_t size, int nc, int sr, int bits) { 349bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten strncpy(RIFF, "RIFF", 4); 359bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten chunkSize = size + sizeof(HeaderWav); 369bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten strncpy(WAVE, "WAVE", 4); 379bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten strncpy(fmt, "fmt ", 4); 389bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten fmtSize = 16; 399bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten audioFormat = 1; 409bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten numChannels = nc; 419bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten samplesRate = sr; 429bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten byteRate = sr * numChannels * (bits/8); 439bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten align = nc*(bits/8); 449bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten bitsPerSample = bits; 459bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten strncpy(data, "data", 4); 469bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten dataSize = size; 479bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten } 489bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten 499bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten char RIFF[4]; // RIFF 509bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten uint32_t chunkSize; // File size 519bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten char WAVE[4]; // WAVE 529bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten char fmt[4]; // fmt\0 539bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten uint32_t fmtSize; // fmt size 549bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten uint16_t audioFormat; // 1=PCM 559bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten uint16_t numChannels; // num channels 569bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten uint32_t samplesRate; // sample rate in hz 579bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten uint32_t byteRate; // Bps 589bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten uint16_t align; // 2=16-bit mono, 4=16-bit stereo 599bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten uint16_t bitsPerSample; // bits per sample 609bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten char data[4]; // "data" 619bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten uint32_t dataSize; // size 629bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten}; 639bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten 649bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kastenstatic int usage(const char* name) { 659bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten fprintf(stderr,"Usage: %s [-p] [-h] [-s] [-q {dq|lq|mq|hq|vhq}] [-i input-sample-rate] " 669bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten "[-o output-sample-rate] [<input-file>] <output-file>\n", name); 679bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten fprintf(stderr," -p enable profiling\n"); 689bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten fprintf(stderr," -h create wav file\n"); 699bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten fprintf(stderr," -s stereo\n"); 709bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten fprintf(stderr," -q resampler quality\n"); 719bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten fprintf(stderr," dq : default quality\n"); 729bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten fprintf(stderr," lq : low quality\n"); 739bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten fprintf(stderr," mq : medium quality\n"); 749bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten fprintf(stderr," hq : high quality\n"); 759bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten fprintf(stderr," vhq : very high quality\n"); 769bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten fprintf(stderr," -i input file sample rate\n"); 779bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten fprintf(stderr," -o output file sample rate\n"); 789bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten return -1; 799bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten} 809bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten 819bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kastenint main(int argc, char* argv[]) { 829bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten 839bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten const char* const progname = argv[0]; 849bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten bool profiling = false; 859bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten bool writeHeader = false; 869bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten int channels = 1; 879bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten int input_freq = 0; 889bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten int output_freq = 0; 899bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten AudioResampler::src_quality quality = AudioResampler::DEFAULT_QUALITY; 909bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten 919bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten int ch; 929bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten while ((ch = getopt(argc, argv, "phsq:i:o:")) != -1) { 939bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten switch (ch) { 949bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten case 'p': 959bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten profiling = true; 969bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten break; 979bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten case 'h': 989bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten writeHeader = true; 999bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten break; 1009bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten case 's': 1019bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten channels = 2; 1029bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten break; 1039bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten case 'q': 1049bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten if (!strcmp(optarg, "dq")) 1059bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten quality = AudioResampler::DEFAULT_QUALITY; 1069bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten else if (!strcmp(optarg, "lq")) 1079bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten quality = AudioResampler::LOW_QUALITY; 1089bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten else if (!strcmp(optarg, "mq")) 1099bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten quality = AudioResampler::MED_QUALITY; 1109bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten else if (!strcmp(optarg, "hq")) 1119bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten quality = AudioResampler::HIGH_QUALITY; 1129bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten else if (!strcmp(optarg, "vhq")) 1139bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten quality = AudioResampler::VERY_HIGH_QUALITY; 1149bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten else { 1159bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten usage(progname); 1169bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten return -1; 1179bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten } 1189bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten break; 1199bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten case 'i': 1209bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten input_freq = atoi(optarg); 1219bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten break; 1229bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten case 'o': 1239bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten output_freq = atoi(optarg); 1249bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten break; 1259bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten case '?': 1269bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten default: 1279bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten usage(progname); 1289bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten return -1; 1299bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten } 1309bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten } 1319bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten argc -= optind; 1329bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten argv += optind; 1339bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten 1349bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten const char* file_in = NULL; 1359bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten const char* file_out = NULL; 1369bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten if (argc == 1) { 1379bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten file_out = argv[0]; 1389bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten } else if (argc == 2) { 1399bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten file_in = argv[0]; 1409bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten file_out = argv[1]; 1419bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten } else { 1429bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten usage(progname); 1439bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten return -1; 1449bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten } 1459bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten 1469bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten // ---------------------------------------------------------- 1479bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten 1489bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten size_t input_size; 1499bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten void* input_vaddr; 1509bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten if (argc == 2) { 1519bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten struct stat st; 1529bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten if (stat(file_in, &st) < 0) { 1539bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten fprintf(stderr, "stat: %s\n", strerror(errno)); 1549bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten return -1; 1559bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten } 1569bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten 1579bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten int input_fd = open(file_in, O_RDONLY); 1589bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten if (input_fd < 0) { 1599bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten fprintf(stderr, "open: %s\n", strerror(errno)); 1609bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten return -1; 1619bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten } 1629bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten 1639bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten input_size = st.st_size; 1649bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten input_vaddr = mmap(0, input_size, PROT_READ, MAP_PRIVATE, input_fd, 0); 1659bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten if (input_vaddr == MAP_FAILED ) { 1669bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten fprintf(stderr, "mmap: %s\n", strerror(errno)); 1679bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten return -1; 1689bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten } 1699bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten } else { 1709bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten double k = 1000; // Hz / s 1719bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten double time = (input_freq / 2) / k; 1729bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten size_t input_frames = size_t(input_freq * time); 1739bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten input_size = channels * sizeof(int16_t) * input_frames; 1749bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten input_vaddr = malloc(input_size); 1759bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten int16_t* in = (int16_t*)input_vaddr; 1769bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten for (size_t i=0 ; i<input_frames ; i++) { 1779bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten double t = double(i) / input_freq; 1789bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten double y = sin(M_PI * k * t * t); 1799bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten int16_t yi = floor(y * 32767.0 + 0.5); 1809bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten for (size_t j=0 ; j<(size_t)channels ; j++) { 1819bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten in[i*channels + j] = yi / (1+j); 1829bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten } 1839bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten } 1849bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten } 1859bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten 1869bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten // ---------------------------------------------------------- 1879bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten 1889bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten class Provider: public AudioBufferProvider { 1899bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten int16_t* mAddr; 1909bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten size_t mNumFrames; 1919bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten public: 1929bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten Provider(const void* addr, size_t size, int channels) { 1939bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten mAddr = (int16_t*) addr; 1949bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten mNumFrames = size / (channels*sizeof(int16_t)); 1959bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten } 1969bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten virtual status_t getNextBuffer(Buffer* buffer, 1979bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten int64_t pts = kInvalidPTS) { 1989bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten buffer->frameCount = mNumFrames; 1999bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten buffer->i16 = mAddr; 2009bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten return NO_ERROR; 2019bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten } 2029bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten virtual void releaseBuffer(Buffer* buffer) { 2039bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten } 2049bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten } provider(input_vaddr, input_size, channels); 2059bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten 2069bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten size_t input_frames = input_size / (channels * sizeof(int16_t)); 2079bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten size_t output_size = 2 * 4 * ((int64_t) input_frames * output_freq) / input_freq; 2089bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten output_size &= ~7; // always stereo, 32-bits 2099bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten 2109bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten void* output_vaddr = malloc(output_size); 2119bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten 2129bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten if (profiling) { 2139bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten AudioResampler* resampler = AudioResampler::create(16, channels, 2149bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten output_freq, quality); 2159bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten 2169bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten size_t out_frames = output_size/8; 2179bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten resampler->setSampleRate(input_freq); 2189bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten resampler->setVolume(0x1000, 0x1000); 2199bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten 2209bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten memset(output_vaddr, 0, output_size); 2219bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten timespec start, end; 2229bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten clock_gettime(CLOCK_MONOTONIC_HR, &start); 2239bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten resampler->resample((int*) output_vaddr, out_frames, &provider); 2249bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten resampler->resample((int*) output_vaddr, out_frames, &provider); 2259bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten resampler->resample((int*) output_vaddr, out_frames, &provider); 2269bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten resampler->resample((int*) output_vaddr, out_frames, &provider); 2279bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten clock_gettime(CLOCK_MONOTONIC_HR, &end); 2289bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten int64_t start_ns = start.tv_sec * 1000000000LL + start.tv_nsec; 2299bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten int64_t end_ns = end.tv_sec * 1000000000LL + end.tv_nsec; 2309bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten int64_t time = (end_ns - start_ns)/4; 2319bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten printf("%f Mspl/s\n", out_frames/(time/1e9)/1e6); 2329bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten 2339bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten delete resampler; 2349bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten } 2359bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten 2369bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten AudioResampler* resampler = AudioResampler::create(16, channels, 2379bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten output_freq, quality); 2389bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten size_t out_frames = output_size/8; 2399bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten resampler->setSampleRate(input_freq); 2409bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten resampler->setVolume(0x1000, 0x1000); 2419bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten 2429bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten memset(output_vaddr, 0, output_size); 2439bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten resampler->resample((int*) output_vaddr, out_frames, &provider); 2449bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten 2459bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten // down-mix (we just truncate and keep the left channel) 2469bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten int32_t* out = (int32_t*) output_vaddr; 2479bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten int16_t* convert = (int16_t*) malloc(out_frames * channels * sizeof(int16_t)); 2489bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten for (size_t i = 0; i < out_frames; i++) { 2499bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten for (int j=0 ; j<channels ; j++) { 2509bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten int32_t s = out[i * 2 + j] >> 12; 2519bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten if (s > 32767) s = 32767; 2529bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten else if (s < -32768) s = -32768; 2539bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten convert[i * channels + j] = int16_t(s); 2549bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten } 2559bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten } 2569bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten 2579bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten // write output to disk 2589bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten int output_fd = open(file_out, O_WRONLY | O_CREAT | O_TRUNC, 2599bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 2609bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten if (output_fd < 0) { 2619bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten fprintf(stderr, "open: %s\n", strerror(errno)); 2629bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten return -1; 2639bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten } 2649bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten 2659bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten if (writeHeader) { 2669bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten HeaderWav wav(out_frames * channels * sizeof(int16_t), channels, output_freq, 16); 2679bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten write(output_fd, &wav, sizeof(wav)); 2689bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten } 2699bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten 2709bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten write(output_fd, convert, out_frames * channels * sizeof(int16_t)); 2719bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten close(output_fd); 2729bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten 2739bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten return 0; 2749bcb476a95a26e62f5706d1f00f4873cf44f9e04Glenn Kasten} 275