Get correct FileLengthFrames with CoreAudio - python

I'm working on converting my Python code to Objective C to run on ios devices. The code about reading audio file. In Python I'm using AudioSegment to read file , The result is 2 separated channels in array.
For example:
Left channel [-1,-2,-3,-4,-5,-6,-7,-8,-9,-10] //length = 10
Right channel [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] //length = 10
So the total length from python is 20
Here is how I get audio output in objective c
float *audioTotal = malloc(fileLengthInFrames * sizeof(float));
SInt16 *inputFrames = (SInt16*)bufferList->mBuffers[0].mData;
for(int i = 0; i < fileLengthInFrames; ++i) {
audioTotal[i] = (float)inputFrames[i];
printf("%f ", audioTotal[i]);
}
And output is :
[-1, 1, -2, 2, -3, 3, -4, 4, -5, 5] // length = 10
So the out put from objective c is mixed left and right channel. So I have to separate them by code:
if (clientFormat.mChannelsPerFrame > 1) {
int indexLeft = 0;
int indexRight = 0;
float *leftAudio = malloc(fileLengthInFrames* sizeof(float));
float *rightAudio = malloc(fileLengthInFrames * sizeof(float));
for(int i = 0; i < fileLengthInFrames; i++) {
if (i%2 == 0) {
leftAudio[indexLeft] = audioTotal[i];
printf("%f ", leftAudio[indexLeft]);
indexLeft ++;
} else {
rightAudio[indexRight] = audioTotal[i];
printf("%f ", rightAudio[indexRight]);
indexRight ++;
}
}
}
And now I have 2 separated channel from objective c:
Left channel [-1,-2,-3,-4,-5] //length = 5
Right channel [ 1, 2, 3, 4, 5] //length = 5
So the total length I got from objective c is 10 compare with 20 in python.
Where is my rest of data? Did I miss some steps? Or wrong configuration?
Thanks for help.

When you have interleaved samples and you "separate them by code", you're forgetting to multiply by channelsPerBuffer (which seems to be interleaved-savvy?), so for stereo you're missing out on half of the samples. Try changing the for loop to
for(int i = 0; i < fileLengthInFrames*channelsPerBuffer; i++) {
// display left and right samples here ...
}
The length of audioTotal should also be fileLengthInFrames*channelsPerBuffer.
p.s. why recalculate fileLengthInFrames if client and file sample rates are the same?

Related

My 2D array does not work properly in Ctypes

main.c:
#include <stdlib.h>
int **function() {
int **information = malloc(5 * sizeof(int));
for (int k = 0; k < 5; k++) {
information[k] = malloc(5 * sizeof(int));
for (int j = 0; j < 5; j++) {
information[k][j] = j;
}
}
return information;
}
main.py
import ctypes
from numpy.ctypeslib import ndpointer
lib = ctypes.CDLL("C:\\Users\\.....\\Desktop\\test9\\a.dll")
lib.function.restype = ndpointer(dtype=ctypes.c_int, shape=(5,5),flags='C')
res = lib.function()
print(res)
Result:
[[222866112 368 222866144 368 222866176]
[ 368 222866208 368 222866672 368]
[ 2 3 4 0 389116888]
[201333630 0 1 2 3]
[ 4 0 389116888 201333630 0]]
I do not know why it gives such an output and I have no problem with the same method in one-dimensional mode
How can I solve this problem?
Edited:
Both methods can be useful
Your code allocates an array of 5 pointers to arrays of 5 int. The allocation for the pointer array is incorrect: instead of int **information = malloc(5 * sizeof(int)); you should write: int **information = malloc(5 * sizeof(*information));
Yet for your purpose, the type int ** is incorrect. You should instead allocate an actual 2D array int array[5][5].
The syntax for a pointer to a dynamically allocated 2D array is cumbersome and the syntax for a function that returns such a pointer is a real challenge:
#include <stdlib.h>
int (*function(void))[5] {
// allocate an array of 5 arrays of 5 int
int (*information)[5] = malloc(5 * sizeof(*information));
// initialize all 5 rows to identical vectors { 0, 1, 2, 3, 4 }
for (int k = 0; k < 5; k++) {
for (int j = 0; j < 5; j++) {
information[k][j] = j;
}
}
return information;
}
The function prototype can be read using the spiral rule: start from the name, read the postfix operators then the prefix operators, switching direction at the parentheses:
function is a function of no arguments returning a pointer to arrays of 5 int.
To use ctypes with int** you can use POINTER(POINTER(c_int)) as the type and use slicing to access the elements of the array. To use ctypes with a C-contiguous 5x5 array using int* then numpy can be used efficiently.
test.c
#include <stdlib.h>
#ifdef _WIN32
# define API __declspec(dllexport)
#else
# define API
#endif
API int **function() {
int **information = malloc(5 * sizeof(int*)); // Note row element is int*
for (int k = 0; k < 5; k++) {
information[k] = malloc(5 * sizeof(int)); // Note col element is int
for (int j = 0; j < 5; j++) {
information[k][j] = k * 5 + j;
}
}
return information;
}
API int *function2() {
int *information = malloc(5 * 5 * sizeof(int)); // 5 x 5 C contiguous shape
for (int k = 0; k < 5; k++) {
for (int j = 0; j < 5; j++) {
information[k * 5 + j] = k * 5 + j;
}
}
return information;
}
test.py
import ctypes as ct
import numpy as np
from pprint import pprint
lib = ct.CDLL('./test')
lib.function.argtypes = ()
lib.function.restype = ct.POINTER(ct.POINTER(ct.c_int))
lib.function2.argtypes = ()
lib.function2.restype = np.ctypeslib.ndpointer(dtype=ct.c_int, shape=(5, 5), flags='C')
def function():
res = lib.function()
# slicing used to extract the correct number of items
return [row[:5] for row in res[:5]]
pprint(function())
pprint(lib.function2())
Output:
[[0, 1, 2, 3, 4],
[5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19],
[20, 21, 22, 23, 24]]
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19],
[20, 21, 22, 23, 24]])
In both cases the memory is leaked for the mallocs. Ideally, let Python manage the memory and let C know the shape. Using np.empty below allocates memory without initialization then C initializes it. This is more flexible and can be used with different-sized arrays:
test.c
#include <stdlib.h>
#ifdef _WIN32
# define API __declspec(dllexport)
#else
# define API
#endif
API void function3(int* information, int row, int col) {
for (int k = 0; k < row; k++) {
for (int j = 0; j < col; j++) {
information[k * row + j] = k * 5 + j;
}
}
}
test.py
import ctypes as ct
import numpy as np
lib = ct.CDLL('./test')
lib.function3.argtypes = np.ctypeslib.ndpointer(dtype=ct.c_int),
lib.function3.restype = None
info = np.empty(dtype=ct.c_int,shape=(5,5))
lib.function3(info,5,5)
print(info)
Output:
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]
[15 16 17 18 19]
[20 21 22 23 24]]

HackerRank "filled orders" problem with Python

Recently HackerRank launched their own certifications. Among the tests they offer is "Problem Solving". The test contains 2 problems; they give you 90 minutes to solve them. Being inexperienced as I am, I failed, because it took me longer than that.
Specifically, I came up with the solution for the first problem (filled orders, see below) in, like 30 minutes, and spent the rest of the time trying to debugg it. The problem with it wasn't that the solution didn't work, but that it worked on only some of the test cases.
Out of 14 testcases the solution worked on 7 (including all the open ones and a bunch of closed ones), and didn't work on the remaining 7 (all closed). Closed means that the input data is not available, as well as expected output. (Which makes sense, because some of the lists there included 250K+ elements.)
But it drives me crazy; I can't figure out what might be wrong with it. I tried putting print statements all over the place, but the only thing I came to is that 1 too many elements get added to the list - hence, the last if statement (to drop the last added element), but it made no difference whatsoever, so it's probably wrong.
Here's the problem:
A widget manufacturer is facing unexpectedly high demand for its new product,. They would like to satisfy as many customers as possible. Given a number of widgets available and a list of customer orders, what is the maximum number of orders the manufacturer can fulfill in full?
Function Description
Complete the function filledOrders in the editor below. The function must return a single integer denoting the maximum possible number of fulfilled orders.
filledOrders has the following parameter(s):
    order :  an array of integers listing the orders
    k : an integer denoting widgets available for shipment
Constraints
1 ≤ n ≤  2 x 105
1 ≤  order[i] ≤  109
1 ≤ k ≤ 109
Sample Input For Custom Testing
2
10
30
40
Sample Output
2
And here's my function:
def filledOrders(order, k):
total = k
fulf = []
for r in order:
if r <= total:
fulf.append(r)
total -= r
else:
break
if sum(fulf) > k:
fulf.pop()
return len(fulf)
Java Solution
int count = 0;
Collections.sort(order);
for(int i=0; i<order.size(); i++) {
if(order.get(i)<=k) {
count++;
k = k - order.get(i);
}
}
return count;
Code Revision
def filledOrders(order, k):
total = 0
for i, v in enumerate(sorted(order)):
if total + v <= k:
total += v # total stays <= k
else:
return i # provides the count
else:
return len(order) # was able to place all orders
print(filledOrders([3, 2, 1], 3)) # Out: 2
print(filledOrders([3, 2, 1], 1)) # Out: 1
print(filledOrders([3, 2, 1], 10)) # Out: 3
print(filledOrders([3, 2, 1], 0)) # Out: 0
Advanced Javascript solution :
function filledOrders(order, k) {
// Write your code here
let count = 0; let total=0;
const ordersLength = order.length;
const sortedOrders = order.sort(function(a,b) {
return (+a) - (+b);
});
for (let i = 0; i < ordersLength; i++) {
if (total + sortedOrders[i] <= k) {
// if all orders able to be filled
if (total <= k && i === ordersLength - 1) return ordersLength;
total += sortedOrders[i];
count++;
} else {
return count;
}
}
}
Python code
def filledOrders(order, k):
orderfulfilled=0
for i in range(1,len(order)):
m=k-order[i]
if(m>=0):
orderfulfilled+=1
k-=order[i]
return(orderfulfilled)
Javascript solution
Option1:
function filledOrders(order, k) {
let count=0;
let arr= [];
arr = order.sort().filter((item, index) => {
if (item<=k) {
k = k - item;
return item
}
})
return arr.length
}
Option2:
function filledOrders(order, k) {
let count=0;
for(var i=0; i<order.sort().length; i++) {
if(order[i]<=k) {
count++;
k = k - order[i]
}
}
return count;
}
C#
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Collections;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text.RegularExpressions;
using System.Text;
using System;
using System.Reflection.Metadata.Ecma335;
class Result
{
/*
* Complete the 'filledOrders' function below.
*
* The function is expected to return an INTEGER.
* The function accepts following parameters:
* 1. INTEGER_ARRAY order
* 2. INTEGER k
*/
public static int filledOrders(List<int> order, int k)
{
if (order.Sum() <= k)
{
return order.Count();
}
else
{
int counter = 0;
foreach (int element in order)
{
if (element <= k)
{
counter++;
k = k - element;
}
}
return counter;
}
}
}
class Solution
{
public static void Main(string[] args)
{
int orderCount = Convert.ToInt32(Console.ReadLine().Trim());
List<int> order = new List<int>();
for (int i = 0; i < orderCount; i++)
{
int orderItem = Convert.ToInt32(Console.ReadLine().Trim());
order.Add(orderItem);
}
int k = Convert.ToInt32(Console.ReadLine().Trim());
var orderedList = order.OrderBy(a=>a).ToList();
int result = Result.filledOrders(orderedList, k);
Console.WriteLine(result);
}
}
I think, the better way to approach (to decrease time complexity) is to solve without use of sorting. (Ofcourse, that comes that cost of readability)
Below is a solution without use of sort. (Not sure if I covered all edge cases.)
import os, sys
def max_fulfilled_orders(order_arr, k):
# track the max no.of orders in the arr.
max_num = 0
# order count, can be fulfilled.
order_count = 0
# iter over order array
for i in range(0, len(order_arr)):
# if remain value < 0 then
if k - order_arr[i] < 0:
# add the max no.of orders to total
k += max_num
if order_count > 0:
# decrease order_count
order_count -= 1
# if the remain value >= 0
if(k - order_arr[i] >= 0):
# subtract the current no.of orders from total.
k -= order_arr[i]
# increase the order count.
order_count += 1
# track the max no.of orders till the point.
if order_arr[i] > max_num:
max_num = order_arr[i]
return order_count
print(max_fulfilled_orders([3, 2, 1], 0)) # Out: 0
print(max_fulfilled_orders([3, 2, 1], 1)) # Out: 1
print(max_fulfilled_orders([3, 1, 1], 2)) # Out: 2
print(max_fulfilled_orders([3, 2, 4], 9)) # Out: 3
print(max_fulfilled_orders([3, 2, 1, 4], 10)) # Out: 4
In python,
def order_fillers(order,k):
if len(order)==0 or k==0:
return 0
order.sort()
max_orders=0
for item in order:
if k<=0:
return max_orders
if item<=k:
max_orders+=1
k-=item
return max_orders
JavaScript Solution
function filledOrders(order, k) {
let total = 0;
let count = 0;
const ordersLength = order.length;
const sortedOrders = order.sort();
for (let i = 0; i < ordersLength; i++) {
if (total + sortedOrders[i] <= k) {
// if all orders able to be filled
if (total <= k && i === ordersLength - 1) return ordersLength;
total += sortedOrders[i];
count++;
} else {
return count;
}
}
}
// Validation
console.log(filledOrders([3, 2, 1], 3)); // 2
console.log(filledOrders([3, 2, 1], 1)); // 1
console.log(filledOrders([3, 2, 1], 10)); // 3
console.log(filledOrders([3, 2, 1], 0)); // 0
console.log(filledOrders([3, 2, 2], 1)); // 0

np.gradient alternative in c++

I need to write a C++ function that caculate the gradient of an array like np.gradient function in numpy:
>>> f = np.array([1, 2, 4, 7, 11, 16], dtype=float)
>>> np.gradient(f)
array([1. , 1.5, 2.5, 3.5, 4.5, 5. ])
Does any one knows how to implement it?
According to the documentation in https://docs.scipy.org/doc/numpy/reference/generated/numpy.gradient.html
f'[x] = (f[x+1] - f[x-1]) / 2.0*h + o(h^2)
so you can go over the elements from 1 to n-1 and calculate (f[i+1] - f[i-1]) / 2.0
for the edges I believe you have to do:
f'[0] = f[1] - f[0]
f'[n] = f[n] = f[n-1]
implemented a very simple function myself since this question is too easy...
vector<double> gradient(vector<double> input){
if (input.size() <= 1) return input;
vector<double> res;
for(int j=0; j<input.size(); j++) {
int j_left = j - 1;
int j_right = j + 1;
if (j_left < 0) {
j_left = 0; // use your own boundary handler
j_right = 1;
}
if (j_right >= input.size()){
j_right = input.size() - 1;
j_left = j_right - 1;
}
// gradient value at position j
double dist_grad = (input[j_right] - input[j_left]) / 2.0;
res.push_back(dist_grad);
}
return res;
}

how C++ insert like python?

I want to implement insert in C++ like this:
// python code
insertIndexes = [1, 1, 2, 2, 3, 3, 5]
arr = []
toInsertValue = 0;
for i in insertIndexes:
arr.insert(i, toInsertValue)
toInsertValue += 1
print arr // [0, 1, 3, 5, 4, 6, 2]
but I find that I have to know vector size if I want to use insert in C++:
// !!C++ wrong code!!
// vec is not initialized correctly
vector<int> vec;
int insertIndexes[] = {1, 1, 2, 2, 3, 3, 5}
int toInsertValue = 0;
for (int i = 0; i < sizeof(insertIndexes)/sizeof(insertIndexes[0]); i++) {
vec.insert(vec.begin() + insertIndexes[i], toInsertValue);
toInsertValue += 1;
}
In Python, inserting at an index outside the list size is very forgiving, the implementation checks that the insert location is greater than or equal to len(list), then the new item is inserted appended. In C++'s std::vector, this is not so. You will have to make that check yourself.
auto offset = 0;
for(auto x : indexes){
if(x < vec.size()) //Is the selected index in range?
vec.insert(vec.begin() + x, offset++);
else
vec.insert(vec.end(), offset++);
}
Full example:
std::vector<int> indexes = {1, 1, 2, 2, 3, 3, 5};
std::vector<int> vec;
auto offset = 0;
for(auto x : indexes){
auto iter = (x < int(vec.size())) ? vec.begin() + x : vec.end();
vec.insert(iter, offset++);
}
std::copy(vec.begin(), vec.end(), std::ostream_iterator<int>(std::cout, " "));
Outputs (As seen Live On Coliru ):
0 1 3 5 4 6 2
When you define a vector without a specific size, it will be empty and all indexing into it (with or without iterators) will be out of bounds leading to undefined behavior.
In your loop you need to check that indexes[i] will not be out of bounds, and if it is then resize the vector appropriately or use push_back to append the value offset to the vector.

How to implement/construct the following permutation, given two n-tuples, efficiently?

I am studying queuing theory in which I am frequently presented with the following situation.
Let x, y both be n-tuples of nonnegative integers (depicting lengths of the n queues). In addition, x and y each have distinguished queue called their "prime queue". For example,
x = [3, 6, 1, 9, 5, 2] with x' = 1
y = [6, 1, 5, 9, 5, 5] with y' = 5
(In accordance with Python terminology I am counting the queues 0-5.)
How can I implement/construct the following permutation f on {0,1,...,5} efficiently?
first set f(x') = y'. So here f(1) = 5.
then set f(i) = i for any i such that x[i] == y[i]. Clearly there is no need to consider the indices x' and y'. So here f(3) = 3 (both length 9) and f(4) = 4 (both length 5).
there are now equally sized sets of queues unpaired in x and in y. So here in x this is {0,2,5} and in y this is {0,1,2}.
rank these from from 1 to s, where s is the common size of the sets, by length with 1 == lowest rank == shortest queue and s == highest rank == longest queue. So here, s = 3, and in x rank(0) = 1, rank(2) = 3 and rank(5) = 2, and in y rank(0) = 1, rank(1) = 3, rank(2) = 2. If there is a tie, give the queue with the larger index the higher rank.
pair these s queues off by rank. So here f(0) = 0, f(2) = 1, f(5) = 2.
This should give the permutation [0, 5, 1, 3, 4, 2].
My solution consists of tracking the indices and loops over x and y multiple times, and is terribly inefficient. (Roughly looking at n >= 1,000,000 in my application.)
Any help would be most appreciated.
Since you must do the ranking, you can't get linear and will need to sort. So it looks pretty straightforward. You do 1. in O(1) and 2. in O(n) by just going over the n-tuples. At the same time, you can construct the copy of x and y with only those that are left for 3. but do not include only the value, but instead use tuple of value and its index in the original.
In your example, x-with-tuples-left would be [[3,0],[1,2],[2,5]] and y-with-tuples-left would be [[6,0],[1,1],[5,2]].
Then just sort both x-with-tuples-left and y-with-tuples-left (it will be O(n.log n)), and read the permutation from the second element of the corresponding tuples.
In your example, sorted x-with-... would be [[1,2],[2,5],[3,0]] and sorted y-with-... would be [[1,1],[5,2],[6,0]]. Now, you nicely see 5. from the second elements: f(2)=1, f(5)=2, f(0)=0.
EDIT: Including O(n+L) in Javascript:
function qperm (x, y, xprime, yprime) {
var i;
var n = x.length;
var qperm = new Array(n);
var countsx = [], countsy = []; // same as new Array()
qperm[xprime] = yprime; // doing 1.
for (i = 0; i < n; ++i) {
if (x[i] == y[i] && i != xprime && i != yprime) { // doing 2.
qperm[i] = i; }
else { // preparing for 4. below
if (i != xprime) {
if (countsx[x[i]]) countsx[x[i]]++; else countsx[x[i]] = 1; }
if (i != yprime) {
if (countsy[y[i]]) countsy[y[i]]++; else countsy[y[i]] = 1; } }
// finishing countsx and countsy
var count, sum;
for (i = 0, count = 0; i < countsx.length; ++i) {
if (countsx[i]) {
sum = count + countsx[i];
countsx[i] = count;
count = sum; }
for (i = 0, count = 0; i < countsy.length; ++i) {
if (countsy[i]) {
sum = count + countsy[i];
countsy[i] = count;
count = sum; }
var yranked = new Array(count);
for (i = 0; i < n; ++i) {
if (i != yprime && (x[i] != y[i] || i == xprime)) { // doing 4. for y
yranked[countsy[y[i]]] = y[i];
countsy[y[i]]++; } }
for (i = 0; i < n; ++i) {
if (i != xprime && (x[i] != y[i] || i == yprime)) { // doing 4. for x and 5. at the same time
// this was here but was not right: qperm[x[i]] = yranked[countsx[x[i]]];
qperm[i] = yranked[countsx[x[i]]];
// this was here but was not right: countsy[y[i]]++; } } }
countsx[x[i]]++; } }
return qperm; }
Hopefully it's correct ;-)

Categories

Resources