how use ADPCM microchips - c++

I have some problems with adpcm in .wav (sound)files.
at first of this question, I should say that I didn't read all things about ADPCM , just wanted to implement that fast and work on it ... (just training code)
I implemented it from MicroChip's pdf guid adpcm.(it's better to say copy/pasted and edited ,created class)
Test code:
const std::vector<int8_t> data = {
64, 67, 71, 75, 79, 83, 87, 91, 94, 98, 101, 104, 107, 110, 112,
115, 117, 119, 121, 123, 124, 125, 126, 126, 127, 127, 127, 126, 126, 125,
124, 123, 121, 119, 117, 115, 112, 110, 107, 104, 101, 98, 94, 91, 87,
83, 79, 75, 71, 67, 64, 60, 56, 52, 48, 44, 40, 36, 33, 29,
26, 23, 20, 17, 15, 12, 10, 8, 6, 4, 3, 2, 1, 1, 0,
0, 0, 1, 1, 2, 3, 4, 6, 8, 10, 12, 15, 17, 20, 23,
26, 29, 33, 36, 40, 44, 48, 52, 56, 60, 64};
void function() {
std::vector<uint8_t> en;
std::vector<uint8_t> de;
{ // encode
wave::ADPCM adpcm;
// 32768
for (size_t i{0}; i < data.size() - 3; i += 4) {
int16_t first{static_cast<int16_t>(
~((static_cast<uint16_t>(data[i]) & 0xff) |
((static_cast<uint16_t>(data[i + 1]) << 8) & 0xff00)) +
1)};
int16_t second{static_cast<int16_t>(
~((static_cast<uint16_t>(data[i + 2]) & 0xff) |
((static_cast<uint16_t>(data[i + 3]) << 8) & 0xff00)) +
1)};
en.push_back(static_cast<uint8_t>((adpcm.ADPCMEncoder(first) & 0x0f) |
(adpcm.ADPCMEncoder(second) << 4)));
}
}
{ // decode
wave::ADPCM adpcm;
for (auto val : en) {
int16_t result = ~adpcm.ADPCMDecoder(val & 0xf) + 1;
int8_t temp0 = ((result)&0xff);
int8_t temp1 = ((result)&0xff00) >> 8;
de.push_back(temp0);
de.push_back(temp1);
result = ~adpcm.ADPCMDecoder(val >> 4) + 1;
temp0 = ((result)&0xff);
temp1 = (result & 0xff00) >> 8;
de.push_back(temp0);
de.push_back(temp1);
}
}
int i{0};
for (auto val : de) {
qDebug() << "real:" << data[i] << "decoded: " << val;
i++;
}
}
I'm sure that my class and encode/decode is right ,just after decode I should do somethings to show correct numbers(but I donw know which casting is failed).
why I'm sure? because when I see my output in QDebug , every other sample(after decode) are correct (with few errors, in big datas errors will be smaller than now), but anothers are failed
my output:
real: 26 decoded: 6
real: 29 decoded: 32
real: 33 decoded: 5
real: 36 decoded: 48
real: 40 decoded: 6
real: 44 decoded: 32
real: 48 decoded: 5
real: 52 decoded: 48
real: 56 decoded: 4
real: 60 decoded: 64
data are 8bits in device

Ok , I found my answer
when you have error on any number , your error is in lower bits!
so my predict was on two numbers that was anded to gether , then that number is in lower bits position have much errors!

Related

Inlined function to return nested array value not performing as expected

I want to inline the function MyClass:at(), but performance isn't as I expect.
MyClass.cpp
#include <algorithm>
#include <chrono>
#include <iostream>
#include <vector>
#include <string>
// Making this a lot shorter than in my actual program
std::vector<std::vector<int>> arrarr =
{
{ 1, 70, 54, 71, 83, 51, 54, 69, 16, 92, 33, 48, 61, 43, 52, 1, 89, 19, 67, 48},
{24, 47, 32, 60, 99, 3, 45, 2, 44, 75, 33, 53, 78, 36, 84, 20, 35, 17, 12, 50},
{32, 98, 81, 28, 64, 23, 67, 10, 26, 38, 40, 67, 59, 54, 70, 66, 18, 38, 64, 70},
{67, 26, 20, 68, 2, 62, 12, 20, 95, 63, 94, 39, 63, 8, 40, 91, 66, 49, 94, 21},
{24, 55, 58, 5, 66, 73, 99, 26, 97, 17, 78, 78, 96, 83, 14, 88, 34, 89, 63, 72},
{21, 36, 23, 9, 75, 0, 76, 44, 20, 45, 35, 14, 0, 61, 33, 97, 34, 31, 33, 95},
{78, 17, 53, 28, 22, 75, 31, 67, 15, 94, 3, 80, 4, 62, 16, 14, 9, 53, 56, 92},
{16, 39, 5, 42, 96, 35, 31, 47, 55, 58, 88, 24, 0, 17, 54, 24, 36, 29, 85, 57},
{86, 56, 0, 48, 35, 71, 89, 7, 5, 44, 44, 37, 44, 60, 21, 58, 51, 54, 17, 58},
{19, 80, 81, 68, 5, 94, 47, 69, 28, 73, 92, 13, 86, 52, 17, 77, 4, 89, 55, 40},
{ 4, 52, 8, 83, 97, 35, 99, 16, 7, 97, 57, 32, 16, 26, 26, 79, 33, 27, 98, 66},
{88, 36, 68, 87, 57, 62, 20, 72, 3, 46, 33, 67, 46, 55, 12, 32, 63, 93, 53, 69},
{ 4, 42, 16, 73, 38, 25, 39, 11, 24, 94, 72, 18, 8, 46, 29, 32, 40, 62, 76, 36},
{20, 69, 36, 41, 72, 30, 23, 88, 34, 62, 99, 69, 82, 67, 59, 85, 74, 4, 36, 16},
{20, 73, 35, 29, 78, 31, 90, 1, 74, 31, 49, 71, 48, 86, 81, 16, 23, 57, 5, 54},
{ 1, 70, 54, 71, 83, 51, 54, 69, 16, 92, 33, 48, 61, 43, 52, 1, 89, 19, 67, 48},
};
class MyClass
{
public:
MyClass(std::vector<std::vector<int>> arr) : arr(arr)
{
rows = arr.size();
cols = arr.at(0).size();
}
inline auto at(int row, int col) const { return arr[row][col]; }
void arithmetic(int n) const;
private:
std::vector<std::vector<int>> arr;
int rows;
int cols;
};
MyClass.cpp:
void MyClass::arithmetic(int n) const
{
using std::chrono::high_resolution_clock;
using std::chrono::duration_cast;
using std::chrono::duration;
using std::chrono::milliseconds;
auto t1 = high_resolution_clock::now();
int highest_product = 0;
for (auto y = 0; y < rows; ++y)
{
for (auto x = 0; x < cols; ++x)
{
// Horizontal product
if (x + n < cols)
{
auto product = 1;
for (auto i = 0; i < n; ++i)
{
product *= at(y, x + i);
}
highest_product = std::max(highest_product, product);
}
}
}
auto t2 = high_resolution_clock::now();
duration<double, std::milli> ms_double = t2 - t1;
std::cout << ms_double.count() << "ms\n";
return highestProduct;
};
Now what I want know is why do I get better performance when I replace product *= at(y, x + i); with product *= arr[y][x+i];? When I test it with the first case, the timing on my large array takes roughly 6.7ms, and the second case takes 5.3ms. I thought when I inlined the function, it should be the same implementation as the second case.
Member function directly defined in the class definition (typically in header files) are implicitly inlined so using inline is useless in this case. inline do not guarantee the function is inlined. It is just an hint for the compiler. The keyword is also an important during the link to avoid the multiple-definition issue. Function that are not make inline can still be inlined if the compiler can see the code of the target function (ie. it is in the same translation unit or link time optimization are applied). For more information about this, please read Why are class member functions inlined?
Note that the inlining is typically performed in the optimization step of compilers (eg. -O1//O1). Thus without optimizations, most compilers will not inline the function.
Using std::vector<std::vector<int>> is not efficient since it is not a contiguous data structure and it require 2 indirection to access an item. Two sub-vectors next to each other can be stored far away in memory likely causing more cache misses (and/or thrashing due to the alignment). Please consider using one big flatten array and access items using y*cols+x where cols is the size of the sub-vectors (20 here). Alternatively a int[16][20] data type should do the job well if the size if fixed at compile-time.
MyClass(std::vector<std::vector<int>> arr) cause the input parameter to be copied (and so all the sub-vectors). Please consider using a const std::vector<std::vector<int>>& type.
While at is convenient for checking bounds at runtime, this feature can strongly decrease performance. Consider using the operator [] if you do not need that. You can use assertions combined with flatten arrays so to get a fast code in release and a safe code in debug (you can enable/disable them by defining the NDEBUG macro).

Difference between C++ openssl/aes and Go crypto/aes

I have two programs on C++ and Go for encrypt data using AES, but they returns different results. Could you explain me the difference? How I can write similar code to get the same result using Go?
C++
g++ aes.cpp -o aes -O3 -lcrypto -std=c++11 && ./aes
#include <iostream>
#include <openssl/aes.h>
using std::cout;
int main(int argc, char const *argv[]) {
uint8_t result[16] = {0};
uint8_t key[32] = {
52, 51, 51, 100, 52, 53, 98, 57, 51, 98, 98, 98, 102, 102, 56, 100,
54, 53, 53, 49, 55, 56, 54, 51, 50, 102, 49, 56, 101, 97, 101, 97,
};
uint8_t data[16] = {
89, 0, 192, 238, 251, 3, 19, 11, 0, 0, 0, 0, 0, 15, 0, 236,
};
AES_KEY ctx;
AES_set_encrypt_key(&key[0], 128, &ctx);
AES_encrypt(data, result, &ctx);
std::cout << "Result: ";
for (auto const& value: result) {
std::cout << unsigned(value) << ",";
}
std::cout << '\n';
return 0;
}
Result: 65,68,199,89,141,129,6,202,211,198,47,54,212,0,243,130
Go
package main
import (
"crypto/aes"
"log"
)
func main() {
result := make([]byte, 16)
key := []byte{
52, 51, 51, 100, 52, 53, 98, 57, 51, 98, 98, 98, 102, 102, 56, 100,
54, 53, 53, 49, 55, 56, 54, 51, 50, 102, 49, 56, 101, 97, 101, 97,
}
data := []byte{89, 0, 192, 238, 251, 3, 19, 11, 0, 0, 0, 0, 0, 15, 0, 236}
cipher, err := aes.NewCipher(key)
if err != nil {
log.Fatal(err)
}
cipher.Encrypt(result, data)
log.Println(result)
}
Result: 18 144 147 200 175 53 202 191 80 17 142 126 228 220 57 180

Vector to Matrix

I am new using Eigen library and I am having problems transform/reshape a vector in a matrix.
I am trying to get an specific row of a matrix and convert it as a matrix, but each time that I do that the result is not what I am expecting.
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> m(8, 9);
m << 11, 12, 13, 14, 15, 16, 17, 18, 19,
21, 22, 23, 24, 25, 26, 27, 28, 29,
31, 32, 33, 34, 35, 36, 37, 38, 39,
41, 42, 43, 44, 45, 46, 47, 48, 49,
51, 52, 53, 54, 55, 56, 57, 58, 59,
61, 62, 63, 64, 65, 66, 67, 68, 69,
71, 72, 73, 74, 75, 76, 77, 78, 79,
81, 82, 83, 84, 85, 86, 87, 88, 89;
std::cout << m << std::endl << std::endl;
Matrix<double,1,Dynamic,RowMajor> B = m.row(0);
std::cout << B << std::endl << std::endl;
Map<Matrix3d,RowMajor> A(B.data(),3,3);
std::cout << A << std::endl << std::endl;
Result
11 14 17
12 15 18
13 16 19
I want:
11 12 13
14 15 16
17 18 19
You dont need to select a row first and then map. Just map directly from m and assign the transpose of map to a matrix A as follows
Matrix3d A = Map<Matrix3d>(m.data()).transpose();
If you don't like transposing then forcing the map to use RowMajor for the destination type works too
Matrix3d A = Map<Matrix<double, 3, 3, RowMajor>>(m.data());
Although, at this small size it doesn't matter. Cheers
You need to get the transpose of the result matrix. I think eigen library is converting a vector to a matrix by picking every n'th element to form a row in a n*n sized vector.

QR decoding with zbar

I'm encoding a byte array into qr code using libqrencode and than try to decode it using zbar library. the programming language is c++.
The problem occurs when the values are >=128. for example when I decode the qr code which contains the following values:
unsigned char data[17]={111, 127, 128, 224, 255, 178, 201,200, 192, 191,22, 17,20, 34, 65 ,23, 76};
symbol->get_data_length() return 25 instead of 17 and when I tried to print the values using this small piece of code:
string input_data = symbol->get_data();
for(int k=0; k< 25; k++)
cout<< (int)((unsigned char)input_data[k])<<", ";
I got the following result:
111, 127, 194, 128, 195, 160, 195, 191, 194, 178, 195, 137, 195, 136, 195, 128, 194, 191, 22, 17, 20, 34, 65, 23, 76,
So as we can notice the values < 128 didn't effected but I got two bytes for every value >=128.
Also I printed the values without casting to unsigned char:
for(int k=0; k< 25; k++)
cout<< (int)input_data[k]<<", ";
and the result is:
111, 127, -62, -128, -61, -96, -61, -65, -62, -78, -61, -119, -61, -120, -61, -128, -62, -65, 22, 17, 20, 34, 65, 23, 76
I solve this problem by the following code:
void process_zbar_output(const string & input_data, vector<unsigned char> & output_data)
{
for (int i = 0; i < input_data.length(); i++)
{
int temp = (int) input_data[i];
// if the original value is >=128 we need to process it to get the original value
if (temp < 0)
{
// if the number is 62 than the original is between 128 and 191
// if the number is 61 than the original is between 192 and 255
if (temp == -62)
output_data.push_back(256 + ((int) input_data[i + 1]));
else
output_data.push_back(256 + ((int) input_data[i + 1] + 64));
i++;
}
else
{
output_data.push_back( input_data[i]);
}
}
}
Can anybody help me with this problem and explain why I got these extra bytes?

Array of Structs cannot read intergers assigned to them c++

I am trying to assign values to the Arrival, BurstTime, and IOTime arrays. It worked fine when I didn't have Arrival[9]. However trying to pass multiple ints into the variable doesn't work. I get -86638*** numbers. I have been trying to find an answer for days, No luck.
This is my struct.
struct ReadyQueue
{
//static const int MAX_NUMBER = 10;
int ArrivalTime[10];
int BurstTime[10];
int IOTime[10];
std::string Name;
};
and my variables
P[0].ArrivalTime[10] = 0, 98, 221, 327, 423, 530, 628, 719, 788 ;
P[1].ArrivalTime[8] = 17, 116, 208, 320, 437, 554, 665, 754 ; // P2
P[2].ArrivalTime[7] = 27, 125, 238, 364, 468, 579, 680; // P3
P[3].ArrivalTime[8] = 45, 155, 276, 392, 515, 642, 739, 820 ; // P4
P[4].ArrivalTime[10] = 62, 186, 343, 489, 603, 715, 807, 887, 952, 997; // P5
P[5].ArrivalTime[7] = 67, 174, 262, 348, 446, 566, 654; // P6
P[6].ArrivalTime[9] = 77, 148, 216, 302, 359, 461, 546, 622, 697; // P7
P[7].ArrivalTime[8] = 83, 196, 306, 409, 499, 608, 702, 773 ; // P8
P[8].ArrivalTime[9] = 92, 192, 296, 386, 492, 599, 692, 734, 803; // P9
P[0].BurstTime[8] = 17 , 18, 17, 16, 14, 16, 14, 15, 15;
P[0].IOTime[8] = 24, 73, 31, 27, 33, 43, 64, 19 ;
P[1].BurstTime[8] = 10, 9, 8, 7, 9, 12, 15, 19 ;
P[1].IOTime[7] = 31, 35, 42, 43, 47, 43, 51 ;
P[2].IOTime[6] = 51, 53, 61, 31, 43, 31 ;
P[2].BurstTime[7] = 18, 23, 24, 22, 21, 20, 12 ;
P[3].BurstTime[8] = 17, 19, 20, 17, 15, 12, 15, 14 ;
P[3].IOTime[7] = 42, 55, 54, 52, 67, 72, 66 ;
P[4].BurstTime[10] = 5, 6, 5, 3, 5, 4, 3, 4, 3, 5 ;
P[4].IOTime[9] = 61, 82, 71, 61, 62, 51, 77, 61, 42 ;
P[5].BurstTime[7] = 10, 12, 14, 11, 15, 13, 11 ;
P[5].IOTime[6] = 35, 41, 33, 32, 41, 29 ;
P[6].BurstTime[7] = 6, 7, 5, 4, 5, 7, 8, 6, 5 ;
P[6].IOTime[8] = 18, 21, 19, 16, 29, 21, 22, 24 ;
P[7].BurstTime[8] = 9, 12, 14, 14, 16, 14, 13, 15 ;
P[7].IOTime[7] = 52, 42, 31, 21, 43, 31, 32 ;
P[8].BurstTime[9] = 6, 4, 6, 6, 7, 4, 5, 5, 4 ;
P[8].BurstTime[8] = 35, 41, 33, 32, 41, 29, 16, 22 ;
Thank you very much
I want to clarify what those assignments do, because I see some wrong answers.
Let's see it with an example:
P[0].ArrivalTime[10] = 0, 98, 221, 327, 423, 530, 628, 719, 788 ;
First, that statement is assigning 0 in the eleventh element of the ArrivalTime array and I don't think you wanted to do this due to ArrivalTime[9] is the last element.
Second, the comma operator evaluates the first operand, discard the result, and then evaluates the second operand and returns his value. In the example you could think this evaluation returns 788, but assign operator have more precedence than comma, so, the statement will evaluate like this:
((P[0].ArrivalTime[10] = 0), 98, 221, 327, 423, 530, 628, 719, 788 ;
Change this:
struct ReadyQueue
{
//static const int MAX_NUMBER = 10;
int ArrivalTime[10];
int BurstTime[10];
int IOTime[10];
std::string Name;
};
to this:
struct Item
{
int ArrivalTime;
int BurstTime;
int IOTime;
};
struct Ready_queue
{
string name;
queue<Item> items;
};
where queue is std::queue.
If that doesn't suit your higher level purpose, then something similar that does suit that (unexplained) purpose.
The main point is an inversion of the logical structure, putting related data together.
Do note that e.g. x = 6, 4, 6, 6, 7, 4, 5, 5, 4 ; is parsed as (x = 6), 4, 6, 6, 7, 4, 5, 5, 4 ; and thus is equivalent to just = 6;. The longwinded expression after the assignment is using the comma operator, which evaluates the expressions in ordinary reading order, producing the value of the last one. Due to the parsing also that final value is discarded.
Please note that my answer contained a mistake which I corrected it: equal operator has a higher priority than the comma operator (it might still contain traces of it)
This is not how you assign an array to a variable.
what you are doing is simply:
assign 788 0 to p[0].ArrivalTime[10] //the 11th element of p[0] which is outside the reserved space for the array
because the comma operator what it does is that it evaluates every one from left to right and return the last value: example:
int i=0,j;
j=i++,(i+=5),i; //j=0 and i=6 //because it is in fact (j=i++),(i+=5),i;
j=(i++,(i+=5),i); //j=6 and i=6
what you are trying to do is assign p[0].arrivalTime to an array of 10. You should do it this way:
P[0].ArrivalTime[0] = 0 ;
P[0].ArrivalTime[1] = 98 ;
...
P[0].ArrivalTime[9] = 788 ;
I don't know any method that assign an array to an array variable after declaration
You cannot do assignments to arrays like this in c/c++. You can use a similar syntax with {} for initializing arrays, but it won't work for what you want to do here. You could use memcpy to copy the arrays into the memory locations in the struct.
memcpy( p[0].ArrivalTime,
(const int[9]) {0, 98, 221, 327, 423, 530, 628, 719, 788},
sizeof(int [9])
);
Note that the comma is an operator which evaluates a list of expressions and returns the value of the last expression. This means that
P[0].ArrivalTime[10] = 0, 98, 221, 327, 423, 530, 628, 719, 788 ;
assigns 0 to the value at index 10 of the array named ArrivalTime and ignores the rest of the list.