Serial.print(byte(freq[0,1]));Serial.print(" ");
Ahh, the comma operator!
In C, a comma is an operator like miltiplication, division, subtraction. It says "evaluate both terms and just use the final value".
So [nobbc]x = foo(), bar(), baz();[/nobbc]
will execute foo(), then bar(), then baz(), and it will assign the return value of baz() to x.
This: [nobbc]byte(freq[0,1])[/nobbc]
will evaluate [nobbc]0,1[/nobbc]
to the numeric value 1. It will then find the memory address of element 1 of the array (the second sub-array of 3 bytes). It will then truncate that to 8 bits long.
So we'd expect your serial.prints to print 3 values, starting somewhere arbitrary and incrementing by 3 each time (potentially wrapping at 256). And that's exactly what you get: 1, 4, 7.
You want
** **[nobbc]byte(freq[0][1])[/nobbc]** **
, and you don't really need that cast to byte.
This translates to "start with the memory adress of the array. Offset 0 element into the array to get the memory address of the first array of 3 bytes. Offset one element1 into that to get the address of the second byte in that array. Then get the byte at that address".
Equivalently:
byte (*step1)[3] = freq; // initial value - a memory address
step1 += 0; // increment by 0 * sizeof(*step1) = 0 * 3 bytes
byte *step2 = *step1; // first de-reference
step2 += 1; // increment by 1 * sizeof(*step2) = 1 * 1 byte
byte result = *step2; // second de-reference
tl;dr: to address mutidmensional arrays, you put the indexes each in their own square brackets
** **[nobbc]freq[0][1][/nobbc]** **