I have 4 arrays and each has different amount of entries. All these arrays are collected in another one. It's implemented like this:
Code in a c library
static const int32_t ONE_COLOR[2] = { RGB_BLACK, RGB_WHITE };
static const int32_t TWO_COLOR[4] = { RGB_WHITE, RGB_RED, RGB_GREEN, RGB_BLUE };
static const int32_t THREE_COLOR[8] = { RGB_BLACK, RGB_RED, RGB_GREEN, RGB_BLUE,
RGB_CYAN, RGB_YELLOW, RGB_MAGENTA, RGB_WHITE };
static const int32_t FOUR_COLOR[16] = { RGB_WHITE, RGB_RED, RGB_GREEN, RGB_BLUE,
RGB_CYAN, RGB_YELLOW, RGB_MAGENTA, RGB_DARK_RED, RGB_DARK_GREEN,
RGB_DARK_BLUE, RGB_LIGHT_BLUE, RGB_LIGHT_GREEN, RGB_ORANGE, RGB_LIME,
RGB_PINK, RGB_LILA };
static const int32_t* COLOR_ARRAY[4] = { ONE_COLOR, TWO_COLOR, THREE_COLOR,
FOUR_COLOR };
How can I access COLOR_ARRAY[1][2] for example?
Thanks for your help :)
Edit
Example code for access:
Code for Arduino
for (i = 0; i < colorsLen; i++) {
n = 0;
for (j = 0; j < colorsWrite; j++) {
if (bitArray[i * colorsWrite + j] == 1) {
n |= 1 << (colorsWrite - 1 - j);
}
}
colors[i] = COLOR_ARRAY[colorsWrite - 1][n];
// testing access
// colors[i] = ONE_COLOR[n];
// colors[i] = n;
}
colorsLen is the length of the array colors and colorsWrite is the amount of bits that can be transmitted with one color.
The purpose is to transmit data via light from a smartphone to an arduino and back. To get more bandwith the data is coded with colors. colorsWrite defines how big colorsLen should be to get all data transmitted.
Well, judging from your question, you access COLOR_ARRAY[1][2] just like that. So the [1] in that expression is: TWO_COLOR[], and the [2] is: RGB_GREEN. So you do access an array as you did.
I.e: const COLOR clr = COLOR_ARRAY[1][2];
I might be missing some part of your question, but I hope it helps or clarifies.
Regards,
Øyvind
EDIT
This answer might give you a pointer
Defining a static array into a C or C++ source file
this line:
n |= 1 << (colorsWrite - 1 - j);
n will be at least 1, because 1<<0 = 1 ... you are using n as index to ONE_COLOR[n] so you cant access the color at index zero which is RGB_BLACK.
Related
I'm studying code to learn about Extended USB Controls and I came across this bit of code shown below. The function reverses an array's order. It's pretty straight forward, except for one thing. Why doesn't the code corrupt the array? Using the source and destination as the same variable should corrupt it, shouldn't it?
/*
* Convert a array of bytes from big endian to little endian and vice versa by inverting it
*/
static
uint8_t *raw_inv(uint8_t *data, int size) {
int ai = 0;
int bi = size - 1;
uint8_t a = 0;
uint8_t b = 0;
while (ai < bi) {
a = data[ai];
b = data[bi];
data[ai] = b;
data[bi] = a;
ai++;
bi--;
}
return data;
}
Ah: It's the 'static' declaration, isn't it?
It uses a and b as temporaries to hold the values it's exchanging. Only one temporary is needed -- this could be rewritten as:
while (ai < bi) {
a = data[ai];
data[ai] = data[bi];
data[bi] = a;
ai++;
bi--;
}
Ok I am new to C, I have programmed in C# for around 10 years now so still getting used to the whole language, Ive been doing great in learning but im still having a few hickups, currently im trying to write a implementation of RC4 used on the Xbox 360 to encrypt KeyVault/Account data.
However Ive run into a snag, the code works but it is outputting the incorrect data, I have provided the original c# code I am working with that I know works and I have provided the snippet of code from my C project, any help / pointers will be much appreciated :)
Original C# Code :
public struct RC4Session
{
public byte[] Key;
public int SBoxLen;
public byte[] SBox;
public int I;
public int J;
}
public static RC4Session RC4CreateSession(byte[] key)
{
RC4Session session = new RC4Session
{
Key = key,
I = 0,
J = 0,
SBoxLen = 0x100,
SBox = new byte[0x100]
};
for (int i = 0; i < session.SBoxLen; i++)
{
session.SBox[i] = (byte)i;
}
int index = 0;
for (int j = 0; j < session.SBoxLen; j++)
{
index = ((index + session.SBox[j]) + key[j % key.Length]) % session.SBoxLen;
byte num4 = session.SBox[index];
session.SBox[index] = session.SBox[j];
session.SBox[j] = num4;
}
return session;
}
public static void RC4Encrypt(ref RC4Session session, byte[] data, int index, int count)
{
int num = index;
do
{
session.I = (session.I + 1) % 0x100;
session.J = (session.J + session.SBox[session.I]) % 0x100;
byte num2 = session.SBox[session.I];
session.SBox[session.I] = session.SBox[session.J];
session.SBox[session.J] = num2;
byte num3 = data[num];
byte num4 = session.SBox[(session.SBox[session.I] + session.SBox[session.J]) % 0x100];
data[num] = (byte)(num3 ^ num4);
num++;
}
while (num != (index + count));
}
Now Here is my own c version :
typedef struct rc4_state {
int s_box_len;
uint8_t* sbox;
int i;
int j;
} rc4_state_t;
unsigned char* HMAC_SHA1(const char* cpukey, const unsigned char* hmac_key) {
unsigned char* digest = malloc(20);
digest = HMAC(EVP_sha1(), cpukey, 16, hmac_key, 16, NULL, NULL);
return digest;
}
void rc4_init(rc4_state_t* state, const uint8_t *key, int keylen)
{
state->i = 0;
state->j = 0;
state->s_box_len = 0x100;
state->sbox = malloc(0x100);
// Init sbox.
int i = 0, index = 0, j = 0;
uint8_t buf;
while(i < state->s_box_len) {
state->sbox[i] = (uint8_t)i;
i++;
}
while(j < state->s_box_len) {
index = ((index + state->sbox[j]) + key[j % keylen]) % state->s_box_len;
buf = state->sbox[index];
state->sbox[index] = (uint8_t)state->sbox[j];
state->sbox[j] = (uint8_t)buf;
j++;
}
}
void rc4_crypt(rc4_state_t* state, const uint8_t *inbuf, uint8_t **outbuf, int buflen)
{
int idx = 0;
uint8_t num, num2, num3;
*outbuf = malloc(buflen);
if (*outbuf) { // do not forget to test for failed allocation
while(idx != buflen) {
state->i = (int)(state->i + 1) % 0x100;
state->j = (int)(state->j + state->sbox[state->i]) % 0x100;
num = (uint8_t)state->sbox[state->i];
state->sbox[state->i] = (uint8_t)state->sbox[state->j];
state->sbox[state->j] = (uint8_t)num;
num2 = (uint8_t)inbuf[idx];
num3 = (uint8_t)state->sbox[(state->sbox[state->i] + (uint8_t)state->sbox[state->j]) % 0x100];
(*outbuf)[idx] = (uint8_t)(num2 ^ num3);
printf("%02X", (*outbuf)[idx]);
idx++;
}
}
printf("\n");
}
Usage (c#) :
byte[] cpukey = new byte[16]
{
...
};
byte[] hmac_key = new byte[16]
{
...
};
byte[] buf = new System.Security.Cryptography.HMACSHA1(cpukey).ComputeHash(hmac_key);
MessageBox.Show(BitConverter.ToString(buf).Replace("-", ""), "");
Usage(c):
const char cpu_key[16] = { 0xXX, 0xXX, 0xXX };
const unsigned char hmac_key[16] = { ... };
unsigned char* buf = HMAC_SHA1(cpu_key, hmac_key);
uint8_t buf2[20];
uint8_t buf3[8] = { 0x1E, 0xF7, 0x94, 0x48, 0x22, 0x26, 0x89, 0x8E }; // Encrypted Xbox 360 data
uint8_t* buf4;
// Allocated 8 bytes out.
buf4 = malloc(8);
int num = 0;
while(num < 20) {
buf2[num] = (uint8_t)buf[num]; // convert const char
num++;
}
rc4_state_t* rc4 = malloc(sizeof(rc4_state_t));
rc4_init(rc4, buf2, 20);
rc4_crypt(rc4, buf3, &buf4, 8);
Now I have the HMACsha1 figured out, im using openssl for that and I confirm I am getting the correct hmac/decryption key its just the rc4 isnt working, Im trying to decrypt part of the Kyevault that should == "Xbox 360"||"58626F7820333630"
The output is currently : "0000008108020000" I do not get any errors in the compilation, again any help would be great ^.^
Thanks to John's help I was able to fix it, it was a error in the c# version, thanks John !
As I remarked in comments, your main problem appeared to involve how the output buffer is managed. You have since revised the question to fix that, but I describe it anyway here, along with some other alternatives for fixing it. The remaining problem is discussed at the end.
Function rc4_crypt() allocates an output buffer for itself, but it has no mechanism to communicate a pointer to the allocated space back to its caller. Your revised usage furthermore exhibits some inconsistency with rc4_crypt() with respect to how the output buffer is expected to be managed.
There are three main ways to approach the problem.
Function rc4_crypt() presently returns nothing, so you could let it continue to allocate the buffer itself, and modify it to return a pointer to the allocated output buffer.
You could modify the type of the outbuf parameter to uint8_t ** to enable rc4_crypt() to set the caller's pointer value indirectly.
You could rely on the caller to manage the output buffer, and make rc4_crypt() just write the output via the pointer passed to it.
The only one of those that might be tricky for you is #2; it would look something like this:
void rc4_crypt(rc4_state_t* state, const uint8_t *inbuf, uint8_t **outbuf, int buflen) {
*outbuf = malloc(buflen);
if (*outbuf) { // do not forget to test for failed allocation
// ...
(*outbuf)[idx] = (uint8_t)(num2 ^ num3);
// ...
}
}
And you would use it like this:
rc4_crypt(rc4, buf3, &buf4, 8);
... without otherwise allocating any memory for buf4.
The caller in any case has the responsibility for freeing the output buffer when it is no longer needed. This is clearer when it performs the allocation itself; you should document that requirement if rc4_crypt() is going to be responsible for the allocation.
The remaining problem appears to be strictly an output problem. You are apparently relying on print statements in rc4_crypt() to report on the encrypted data. I have no problem whatever with debugging via print statements, but you do need to be careful to print the data you actually want to examine. In this case you do not. You update the joint buffer index idx at the end of the encryption loop before printing a byte from the output buffer. As a result, at each iteration you print not the encrypted byte value you've just computed, but rather an indeterminate value that happens to be in the next position of the output buffer.
Move the idx++ to the very end of the loop to fix this problem, or change it from a while loop to a for loop and increment idx in the third term of the loop control statement. In fact, I strongly recommend for loops over while loops where the former are a good fit to the structure of the code (as here); I daresay you would not have made this mistake if your loop had been structured that way.
Suppose I have 8-bits (mono and stereo) .wav files.
When processing of this file I have to declare pointer to array of samples.
Suppose I create array for samples. Then if it is mono, I read each sample using for(i = 0; i < n; i++ ).
Q: How can I access right and left channels separately (stereo)?
PS
I've read a lot about "mono, stereo and *.wave" but still I can't understand how can I realise access to each channell separately...
You still have array of samples, the question is how you address individual values. This is how you do it:
const UCHAR* pnSamples = ...
if(bMono)
{
for(INT nIndex = 0; ...)
{
const UCHAR nSample = pnSamples[nIndex];
// ...
}
} else
if(bStereo)
{
for(INT nIndex = 0; ...)
{
const UCHAR nLeftSample = pnSamples[2 * nIndex + 0];
const UCHAR nRightSample = pnSamples[2 * nIndex + 1];
// ...
}
}
int eye[3][3] = {
{ 1,0,0 },
{ 0,1,0 },
{ 0,0,1 }
};
Is there a shorter way to initialize it? It's so regular that there must be a smarter way to initialize it, especially if it's more than 3x3, say 10x10 or more.
In c99 you can write:
int eye[][3] = { [0][0] = 1, [1][1] = 1, [2][2] = 1 };
all other elements are zeroed, moreover the compiler figures out the size of the array for you. Just don't skip the second size (3).
Btw. in your code you don't have to use the double braces, this would be fine too:
int eye[3][3] = {
1,0,0,
0,1,0,
1,0,1,
};
In c99 you can also leave the trailing comma, just for symmetry and future refactorings
Other solutions probably require you to write some code, which may indeed save you some time/space in file. But note that this way you're splitting declaration and "initialization", which in case of e.g. globals can make a difference.
You can use designated initializers:
int eye[3][3] = { [0][0]=1, [1][1]=1, [2][2]=1};
All the other elements will be initialized to 0 as per C standard's guarantee.
You may try the following:
#define SIZE 3
int eye[SIZE][SIZE] = {0};
for (int i = 0; i < SIZE ; ++i)
{
eye[i][i] = 1;
}
If you want to store {{ 1,0,0 }, { 0,1,0 }, ...} this style of values in square matrix means, you can write a simple logic as below.
#define SIZE 3
int eye[SIZE][SIZE] = {0};
int *p = (int *)eye;
for (i = 0; i < (SIZE * SIZE); i = i + (SIZE + 1))
{
p[i] = 1;
}
or
for (i = 0; i < SIZE; i++)
{
for (j = 0; j < SIZE; j++)
{
if (i == j)
{
eye[i][j] = 1;
}
else
{
eye[i][j] = 0;
}
}
}
Note : Above logic is only for the sample value you have given. So try to find similar logic if your values are having some relation. If not so, then no other way to initialize it directly even if size of matrix is 1000x1000.
I have the following issue here: I get a block of bytes (uint16_t*) representing audio data, and the device generating them is capturing mono sound, so obviously I have mono audio data, on 1 channel. I need to pass this data to another device, which is expecting interleaved stereo data (so, 2 channels). What I want to do is basically duplicate the 1 channel in data so that both channels of the stereo data will contain the same bytes. Can you point me to an efficient algorithm doing this?
Thanks,
f.
If you just want interleaved stereo samples then you could use a function like this:
void interleave(const uint16_t * in_L, // mono input buffer (left channel)
const uint16_t * in_R, // mono input buffer (right channel)
uint16_t * out, // stereo output buffer
const size_t num_samples) // number of samples
{
for (size_t i = 0; i < num_samples; ++i)
{
out[i * 2] = in_L[i];
out[i * 2 + 1] = in_R[i];
}
}
To generate stereo from a single mono buffer then you would just pass the same pointer for in_L and in_R, e.g.
interleave(mono_buffer, mono_buffer, stereo_buffer, num_samples);
You might want to do the conversion in-place to save some memory. Depends on how small an amount of memory the device in question has. So you might want to use something like this instead of Paul R's approach:
void interleave(uint16_t buf[], const int len)
{
for (int i = len / 2 - 1, j = len - 1; i >= 0; --i) {
buf[j--] = buf[i];
buf[j--] = buf[i];
}
}
When getting the sound data from the mono device, you allocate a buffer that's twice as big as needed and pass that to the mono device. This will fill half the buffer with mono audio. You then pass that buffer to the above function, which converts it to stereo. And finally you pass the buffer to the stereo device. You save an extra allocation and thus use 33% less memory for the conversion.
Pass to both channels the same pointer? If that violates restrict rules, use memcpy()?
Sorry, but your question is otherwise to broad. API? OS? CPUArchitectures?
You are going to have to copy the buffer and duplicate it. As you haven't told us the format, how it is terminated, I can't give code, but it will look like a simple for loop.
int_16* allocateInterleaved(int_16* data, int length)
int i;
int *copy = malloc(sizeof(int_16)*length*2);
if(copy == NULL) {
/* handle error */
}
for(i =0; i<length; i++) {
copy[2*i] = data[i];
copy[2*i+1] = data[i];
}
return copy;
}
forgive any glaring typos, my C is a bit rusty. typdef in whatever type you need for signed 16bit into int_16. Don't forget to free the copy buffer, or better yet reuse it.
You need to interleave the data, but if the frame length is anything greater than one, none of the above solutions will work. The below code can account for variable frame lengths.
void Interleave(BYTE* left, BYTE* right, BYTE* stereo,int numSamples_in, int frameSize)
{
int writeIndex = 0;
for (size_t j = 0; j < numSamples_in; j++)
{
for (int k = 0; k < frameSize; k++)
{
int index = j * frameSize + k;
stereo[k + writeIndex] = left[index];
stereo[k + writeIndex + frameSize] = right[index];
}
writeIndex += 2 * frameSize;
}
}