Related
I have a problem with the FrameOutputNode of the UWP Audio Graph API. I have a very simple graph that reads audio from a wav (PCM 16000Hz, 16 bit mono) file and sends it to the frame output node for processing. When processing, I need the audio to be in shorts (as they are in the raw bytes of the file). But as I read here the data can only be read as floats.
Here is my code:
var encoding = MediaEncodingProfile.CreateWav(AudioEncodingQuality.Low);
encoding.Audio = AudioEncodingProperties.CreatePcm(16000, 1, 16);
AudioGraphSettings settings = new AudioGraphSettings(AudioRenderCategory.Media);
settings.EncodingProperties = encoding.Audio;
CreateAudioGraphResult result = await AudioGraph.CreateAsync(settings);
var graph = result.Graph;
var localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
StorageFile file = await localFolder.GetFileAsync("audio.wav");
var fileInputNodeResult = await graph.CreateFileInputNodeAsync(file);
var fileInputNode = fileInputNodeResult.FileInputNode;
fileInputNode.FileCompleted += async (AudioFileInputNode sender, object args) =>
{
graph.Stop();
}
frameOutputNode = graph.CreateFrameOutputNode(encoding.Audio);
fileInputNode.AddOutgoingConnection(frameOutputNode);
graph.QuantumStarted+= AudioGraph_QuantumStarted;
With the following AudioGraph_QuantumStarted event handler:
private void AudioGraph_QuantumStarted(AudioGraph sender, object args)
{
AudioFrame frame = frameOutputNode.GetFrame();
ProcessFrameOutput(frame);
}
unsafe private void ProcessFrameOutput(AudioFrame frame)
{
AudioBuffer buffer = frame.LockBuffer(AudioBufferAccessMode.Read);
IMemoryBufferReference reference = buffer.CreateReference();
((IMemoryBufferByteAccess)reference).GetBuffer(out byte* dataInBytes, out uint capacityInBytes);
if (capacityInBytes > 0) {
// Read the first 20 bytes
for (int i = 0; i < 20; i++)
{
Debug.WriteLine(dataInBytes[i]);
}
}
}
The bytes I receive in the output are the following. Since the samples are returned as bytes of a float, I marked the sample boundary with a line.
0 0 0 0 | 0 0 0 184 | 0 0 128 184 | 0 0 0 184 ...
But when I read the actual bytes from the file with a byte reader:
FileStream fIn = new FileStream(#"/path/to/audio.wav", FileMode.Open);
BinaryReader br = new BinaryReader(fIn);
// Skip the first 44 bytes since they are header stuff
br.ReadBytes(44);
for (int i = 0; i < 20; i++)
{
Debug.WriteLine(br.ReadByte());
}
Then I get the actual bytes:
0 0 | 255 255 | 254 255 | 255 255 | 255 255 | 254 255 | 253 255 | 252 255 ...
Again I marked the individual samples (shorts -> two bytes) with a line.
As you can see the short bytes 255 255 somehow map to float bytes 0 0 0 184 as they reoccur. So what is that mapping? How can I retrieve the raw shorts from the floats? What do I need to do to actually read the wav file bytes?
My question was answered here. Basically, the floats are the range of the shorts -32768 to 32767 converted to range -1 to 1 in float.
So given a float x in the buffer (use (float*)dataInFloats = (float*)dataInBytes to convert) you can calculate the corresponding short with:
f(x) = (65535 * x - 1) / 2
I want to convert a string into a bitmap or something I can show in a pixelbox.
My string looks like this:
string rxstring = "010010010020020020030030030040040040050050050060060060070070070080080080090090090100100100110110110120120120130130130140140140150150150160160160“
It is no problem to erase the RGB code in the string
("01002003004005060070080090100110120130140150160");
I only need it to show, the is not important [sic]
IDE: VS2010 C#
I'm afraid the data you are getting is not a meaningful image. If you split the data into groups of three. You get the following:
010
010
010
020
020
020
030
030
030
040
040
040
050
050
050
060
060
060
070
070
070
080
080
080
090
090
090
100
100
100
110
110
110
120
120
120
130
130
130
140
140
140
150
150
150
160
160
160
If you look at that data there's no way you can convert this to an image that would actually mean something to us. It would be a collection of 48 pixels. Containing a sort of gradient like image (since the numbers below follow a pattern that is constantly increasing.
We would need more information to debug this. (Like what component is providing the data etc.)
Update
This is what I get when I convert your data to pixels (take in account i've enlarged every pixel to 16x16)
Upon continuing review, I realized that the string your getting isn't a byte array. This creates a square Bitmap and lets you set the values pixel by pixel.
List<string> splitBytes = new List<string>();
string byteString = "";
foreach (var chr in rsstring)
{
byteString += chr;
if (byteString.Length == 3)
{
splitBytes.Add(byteString);
byteString = "";
}
}
var pixelCount = splitBytes.Count / 3;
var numRows = pixelCount / 4;
var numCols = pixelCount / 4;
System.Drawing.Bitmap map = new System.Drawing.Bitmap(numRows, numCols);
var curPixel = 0;
for (int y = 0; y < numCols; y++)
{
for (int x = 0; x < numRows; x++ )
{
map.SetPixel(x, y, System.Drawing.Color.FromArgb(
Convert.ToInt32(splitBytes[curPixel * 3]),
Convert.ToInt32(splitBytes[curPixel * 3 + 1]),
Convert.ToInt32(splitBytes[curPixel * 3 + 2])));
curPixel++;
}
}
//Do something with image
EDIT: Made corrections to the row/col iterations to match the image shown above.
Try converting the string to a byte array and loading it into a memory stream. Once in the stream, you should be able to convert to an image.
List<byte> splitBytes = new List<byte>();
string byteString = "";
foreach (var chr in testString)
{
byteString += chr;
if (byteString.Length == 3)
{
splitBytes.Add(Convert.ToByte(byteString));
byteString = "";
}
}
if (byteString != "")
splitBytes.AddRange(Encoding.ASCII.GetBytes(byteString));
using (var ms = new MemoryStream(splitBytes.ToArray()))
{
var img = System.Drawing.Image.FromStream(ms);
//do something with image.
}
EDIT: Added updated code. This was tested by loading an image of my own and converting the bytes into a string, then converting them back into a byte array using the above code and I successfully loaded the image from a string.
string testString = "255216255224000016074070073070000001001001000096000096000000255225000104069120105102000000077077000042000000000008000004001026000005000000000001000000000062001027000005000000000001000000000070001040000003000000000001000002000000001049000002000000000018000000000078000000000000000000000096000000000001000000000096000000000001080097105110116046078069084032118051046053046049049000255219000067000002001001002001001002002002002002002002002003005003003003003003006004004003005007006007007007006007007008009011009008008010008007007010013010010011012012012012007009014015013012014011012012012255219000067001002002002003003003006003003006012008007008012012012012012012012012012012012012012012012012012012012012012012012012012012012012012012012012012012012012012012012012012012012012012012012012012012255192000017008000004000004003001034000002017001003017001255196000031000000001005001001001001001001000000000000000000000000001002003004005006007008009010011255196000181016000002001003003002004003005005004004000000001125001002003000004017005018033049065006019081097007034113020050129145161008035066177193021082209240036051098114130009010022023024025026037038039040041042052053054055056057058067068069070071072073074083084085086087088089090099100101102103104105106115116117118119120121122131132133134135136137138146147148149150151152153154162163164165166167168169170178179180181182183184185186194195196197198199200201202210211212213214215216217218225226227228229230231232233234241242243244245246247248249250255196000031001000003001001001001001001001001001000000000000000000001002003004005006007008009010011255196000181017000002001002004004003004007005004004000001002119000001002003017004005033049006018065081007097113019034050129008020066145161177193009035051082240021098114209010022036052225037241023024025026038039040041042053054055056057058067068069070071072073074083084085086087088089090099100101102103104105106115116117118119120121122130131132133134135136137138146147148149150151152153154162163164165166167168169170178179180181182183184185186194195196197198199200201202210211212213214215216217218226227228229230231232233234242243244245246247248249250255218000012003001000002017003017000063000252225248089251085248195193031007060033030133127054137107121166121143107103121116176043069052182202085076167111238224143056234193152252204073040162128063255217";
EDIT: Added a sample string of the image I used to test the above code.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
Ref links:
https://lh4.googleusercontent.com/-ceLtiOLVtME/UMBL1yf4RpI/AAAAAAAAAD0/itid5KibW_I/s1015/Doc1.png
https://lh6.googleusercontent.com/-nrphBDA6sjk/UMA_Ukh7ZSI/AAAAAAAAADY/LwjkgobOaBg/s846/MappingTable.png
Updated
I have changed the image convertion by using the LockBits now but failed. Does anyone can give me some suggestion?
/// <summary>
/// Orginal command Format in Decimal:
/// 29[GS], 40[(], 76[L], pL, PH, 48(m), 67[fn], 48[a], kc1, kc2, b, xL, xH, yL, yH, c, [d1 -- dk]
/// pL = Lower bit of sum of parameters (m to dk) = 11(m to c) + last bit of image
/// pH = Higher bit of sum of parameters (m to dk) = 11(m to c) + last bit of image
/// kc = Key Code of NVRam, kc1 = first bit of key code, kc2 = second bit of key code. P.S.: The key code will be hardcode H1.
/// b = number of colors = 1
/// xL & xH = Lower bit of image width, e.g. Width = 128 = 0x0080 then xL = 0x80, xH = 0x00
/// </summary>
/// <param name="pLogo"></param>
public void LoadImageToPrinter(Bitmap pLogo)
{
BitmapData oBmpData = pLogo.LockBits(new Rectangle(0, 0, pLogo.Width, pLogo.Height), ImageLockMode.ReadOnly, pLogo.PixelFormat);
//The list contains all the commands in Decimal format
List<int> oCommandList = new List<int>();
//k = (int((xL + xH × 256) + 7)/8) × (yL + yH × 256)
string HexValueOfX = pLogo.Width.ToString("X4");
string HexValueOfY = pLogo.Height.ToString("X4");
//k
int oExpectedImageByteCount = Math.Abs(oBmpData.Stride) * pLogo.Height;
//Total bit used for parameters
int oTotalParameterBitCount = 11 + oExpectedImageByteCount;
//The hex value for the oTotalParameterBitCount
string oTotalParameterBitCountInHex = oTotalParameterBitCount.ToString("X4").PadLeft(4, '0');
//GS, (, L
oCommandList.AddRange(new int[] { 29, 40, 76 });
//pL
oCommandList.Add(GetLowerHexValue(oTotalParameterBitCountInHex));
//pH
oCommandList.Add(GetHigherHexValue(oTotalParameterBitCountInHex));
//m, fn, a, kc1, kc2, b
oCommandList.AddRange(new int[] { 48, 67, 48, (int)'H', (int)'1', 1 });
//xL, xH
oCommandList.AddRange(new int[] { GetLowerHexValue(HexValueOfX), GetHigherHexValue(HexValueOfX) });
//yL, yH, c
oCommandList.AddRange(new int[] { GetLowerHexValue(HexValueOfY), GetHigherHexValue(HexValueOfY), 49 });
//Append the image bit to the List
byte[] oImageByte = new byte[oExpectedImageByteCount];
IntPtr oPtr = oBmpData.Scan0;
Marshal.Copy(oPtr, oImageByte, 0, oExpectedImageByteCount);
pLogo.UnlockBits(oBmpData);
//Clear NVRam
mThermalPrinterLibrary.Write(new int[] { 29, 40, 76, 5, 0, 48, 65, 67, 76, 82 }.IntArrayToCharString());
//Store graphics data
mThermalPrinterLibrary.Write(oCommandList.ToArray().IntArrayToCharString());
mThermalPrinterLibrary.Write(oImageByte);
//Print the graphics data
mThermalPrinterLibrary.Write(new int[] { 29, 40, 76, 6, 0, 48, 69, (int)'H', (int)'1', 1, 1 }.IntArrayToCharString());
}
I've done this before many years ago, in C. I don't have the code to hand, but it's more than just a snippet. To do this you will need to do the following.
Understand the BMP file format - assuming you're reading your Bitmap from a file.
Look at WINGDI.H (Microsoft Windows SDK) which has C-style definitions of the file headers etc: BITMAPFILEHEADER, BITMAPCOREHEADER, BITMAPINFOHEADER.
Process the headers to determine if the bitmap meets your requirement (for example, to simplify your processing, you might want to insist that the bitmap is exactly 128 x 98 (BITMAPINFOHEADER.biWidth, BITMAPINFOHEADER.biHeight), has one plane (BITMAPINFOHEADER.biPlanes = 1), is monochrome (BITMAPINFOHEADER.biBitCount =1 ), is not compressed (BITMAPINFOHEADER.biCompression = 0). These restrictions aren't absolutely necessary, but will simplify your processing.
Process the pixel array, and convert it to the format required for the ESCPOS escape sequence.
Alternatively, you might want to abandon using ESCPOS, and instead use OPOS / UPOS / POS for .NET, which provides a higher-level API for accessing POS peripherals: the POSPrinter device exposes a method to print a bitmap, and avoids you needing to do the format conversion yourself. You'll need to download the Epson OPOS ADK to do this.
Good luck!
UPDATE
And the document from EPSON just like hell, doesn't understand what it needs.
What's your difficulty with the document from Epson? Maybe you could try asking specific questions about the bits you don't understand.
UPDATE 2
Here are some pointers:
GS ( L pL pH m fn [params] : pL and pH are the low- and high-order bytes of a 16-bit integer value that specifies the length in bytes of the following data (i.e. m fn [params]).
For fn = 67 (Define NV data raster format), the format is GS ( L pL pH m fn a kc1 kc2 b xL xH yL yH [c d1...dk]1...[c d1...dk]b where m = 48, fn = 67, a = 48.
kc1 and kc2 are key codes used to identify the downloaded data when you print it
b specifies the number of colors for the downloaded data, 1 for monochrome, 2 for two-color.
xL and xH are low- and high-order bytes of a 16-bit integer value that defines the width in dots (pixels) of the image.
yL and yH are low- and high-order bytes of a 16-bit integer value that defines the height in dots (pixels) of the image.
For a monochrome bitmap there will be one block c d1 ... dk that specifies the color c and the pixel data. For color bitmaps, there is one block c d1 ... dk per color.
The pixel data d1 ... dk has k bytes where k = (width x (height+7))/8. A bit set to 1 means print that dot (pixel).
I don't know if the above is any clearer to you than the notes in the Epson documentation; if not say which bits you don't understand.
UPDATE 3
Here's an example based on a 128 width x 98 height bitmap as indicated in your question, monochrome for simplicity.
You'll need k = (int(width + 7)/8) × (height) = (int(128+7)/8) x 98 = 16 x 98 = 1568 bytes of pixel data (bit = 1 means dot printed): d1 to d1568
Assume color c = Color 1 = 49 decimal = 0x31 hex (could also be 0x32 or 0x33)
Width = 128 = 0x0080, so xH = 0x00, xL = 0x80
Height = 98 = 0x0062, so yH = 0x00, yL = 0x62
b = number of colors = 1
Assume your key is "H1", i.e. kc1 = 'H' = 0x48 and kc2 = '1' = 0x31
param length = length of m fn a kc1 kc2 b xL xH yL yH c d1 ... d1568 = 11 + 1568 = 1579 = 0x062B hex, so pL = 0x2B, pH = 0x06.
So the data you send will be:
GS ( L pL pH m fn a kc1 kc2 b xL xH yL yH c d1...d1568
In Hex:
1D 28 4C 2B 06 30 43 30 48 31 01 80 00 62 00 31 d1 ... d1568
I'm looking to convert ADPCM data into PCM data from an XNA's .xnb file. (So many abbreviations!)
I've used a couple of places for references, including:
http://www.wooji-juice.com/blog/iphone-openal-ima4-adpcm.html
http://www.cs.columbia.edu/~hgs/audio/dvi/p34.jpg and a couple of others.
I believe that I'm close, as I'm getting a sound that's somewhat similar, but there's a lot of static/corruption in the output sound and I can't seem to figure out why.
The conversion comes down to two functions.
private static byte[] convert(byte[] data)
{
byte[] convertedData = new byte[(data.Length) * 4];
stepSize = 7;
newSample = 0;
index = 0;
var writeCounter = 0;
for (var x = 4; x < data.Length; x++)
{
// First 4 bytes of a block contain initialization information
if ((x % blockSize) < 4)
{
if (x % blockSize == 0) // New block
{
// set predictor/NewSample and index from
// the preamble of the block.
newSample = (short)(data[x + 1] | data[x]);
index = data[x + 2];
}
continue;
}
// Get the first 4 bits from the byte array,
var convertedSample = calculateNewSample((byte)(data[x] >> 4)); // convert 4 bit ADPCM sample to 16 bit PCM sample
// Store 16 bit PCM sample into output byte array
convertedData[writeCounter++] = (byte)convertedSample >> 8;
convertedData[writeCounter++] = (byte)convertedSample & 0x0ff;;
// Convert the next 4 bits of the 8 bit array.
convertedSample = calculateNewSample((byte)(data[x] & 0x0f)); // convert 4 bit ADPCM sample to 16 bit PCM sample.
// Store 16 bit PCM sample into output byte array
convertedData[writeCounter++] = (byte)(convertedSample >> 8);
convertedData[writeCounter++] = (byte)(convertedSample & 0x0ff);
}
// Conversion complete, return data
return convertedData;
}
private static short calculateNewSample(byte sample)
{
Debug.Assert(sample < 16, "Bad sample!");
var indexTable = new int[16] { -1, -1, -1, -1, 2, 4, 6, 8, -1, -1, -1, -1, 2, 4, 6, 8 };
var stepSizeTable = new int[89] { 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767};
var sign = sample & 8;
var delta = sample & 7;
var difference = stepSize >> 3;
// originalsample + 0.5 * stepSize / 4 + stepSize / 8 optimization.
//http://www.cs.columbia.edu/~hgs/audio/dvi/p34.jpg
if ((delta & 4) != 0)
difference += stepSize;
if ((delta & 2) != 0)
difference += stepSize >> 1;
if ((delta & 1) != 0)
difference += stepSize >> 2;
if (sign != 0)
newSample -= (short)difference;
else
newSample += (short)difference;
// Increment index
index += indexTable[sample];
index = (int)MathHelper.Clamp(index, 0, 88);
newSample = (short)MathHelper.Clamp(newSample, -32768, 32767); // clamp between appropriate ranges
// compute new stepSize.
stepSize = stepSizeTable[index];
return newSample;
}
I don't believe the actual calculateNewSample() function is incorrect, as I've passed it the input values from http://www.cs.columbia.edu/~hgs/audio/dvi/p35.jpg and recieved the same output they have. I've tried flipping between the high/low order bytes to see if I've got that backwards to no avail as well. I feel like there's possibly something fundamental that I'm missing out on, but am having trouble finding it.
Any help would be seriously appreciated.
i am trying to create music major scale converter.
Dose anyone have info how do to it
so far i have
rootNote is scale base note like cMajor or gMajor
note is note that i want to convert into major scale 0-126
if i insert rootNote 60 and note 60 the right return would be 0,
if i insert rootNote 60 and note 61 the right return would be 2,
if i insert rootNote 60 and note 62 the right return would be 4,
if i insert rootNote 60 and note 63 the right return would be 5,
if i insert rootNote 61 and note 60 the right return would be 0,
if i insert rootNote 61 and note 61 the right return would be 1,
if i insert rootNote 61 and note 62 the right return would be 3,
if i insert rootNote 61 and note 63 the right return would be 5,
ok i have this other one and it seems to work
i want to map my sequence out put in major scale
but is there some kind of formula what can i use?
.
public int getINMajorScale(int note, int rootNote)
{
List<int> majorScale = new List<int>();
//int bNote = (int)_bNote.CurrentValue;
int bNoteMpl = bNote / 12;
bNote = 12 + (bNote - (12 * bNoteMpl)) - 7;
majorScale.Add(bNote + (12 * bNoteMpl));
int tBnote = bNote;
int res = 0;
for (int i = bNote; i < bNote + 6; i++)
{
//algorytm
res = tBnote + 7;
int mod = 0;
if (res >= 12)
{
mod = res / 12;
res = res - 12 * mod;
}
tBnote = res;
majorScale.Add(res + (bNoteMpl * 12));
}
majorScale.Sort();
int modNuller = 0;
if (nmr >= 7)
{
modNuller = nmr / 7;
nmr = nmr - 7 * modNuller;
}
return (majorScale[nmr] + (modNuller *12));
}
but it's obviously faulty.
Problems with the code as it stands:
modScaling does nothing more than rootNote % 12 as you always pass in 0 and 11
You define mNote but never use it
i is never used in the for loop and so each of the 5 iterations prints the same thing.
OK, lets translate your examples into actual notes to make it easier to understand (numbers presumably correspond to MIDI notes):
rootNote = 60 (C), note = 60 (C) - output 0
rootNote = 60 (C), note = 61 (C#) - output 2
rootNote = 60 (C), note = 62 (D) - output 4
rootNote = 60 (C), note = 63 (D#) - output 5
rootNote = 61 (C#), note = 60 (C) - output 0
rootNote = 61 (C#), note = 61 (C#) - output 1
rootNote = 61 (C#), note = 62 (D) - output 3
rootNote = 61 (C#), note = 63 (D#) - output 5
I might be being really dense but I'm afraid I can't see the pattern there.
A Major scale is of course made up of the sequence Tone, Tone, Semi-tone, Tone, Tone, Tone, Semi-tone, but how does that map to your outputs?
Given your input-outputs, I think I know what you are looking for.
determine steps = note - rootNote
determine interval = number of semi-tones between rootNote and the note steps up the scale
determine phase = rootNote - 60
This algorithm provides accurate results:
static int getINMajorScale(int note, int rootNote)
{
if (note < rootNote) return 0;
var scale = new[] { 2, 2, 1, 2, 2, 2, 1 };
var phase = rootNote - 60;
var steps = note - rootNote;
var interval = steps == 0
? 0 : Enumerable.Range(0, steps).Sum(step => scale[step % scale.Length]);
var number = phase + interval;
return number;
}
yielding:
static void Main(string[] args)
{
//rootNote = 60(C), note = 60(C) - output 0
//rootNote = 60(C), note = 61(C#) - output 2
//rootNote = 60(C), note = 62(D) - output 4
//rootNote = 60(C), note = 63(D#) - output 5
//rootNote = 61(C#), note = 60 (C) - output 0
//rootNote = 61(C#), note = 61 (C#) - output 1
//rootNote = 61(C#), note = 62 (D) - output 3
//rootNote = 61(C#), note = 63 (D#) - output 5
Console.WriteLine(getINMajorScale(60, 60)); // 0
Console.WriteLine(getINMajorScale(61, 60)); // 2
Console.WriteLine(getINMajorScale(62, 60)); // 4
Console.WriteLine(getINMajorScale(63, 60)); // 5
Console.WriteLine(getINMajorScale(60, 61)); // 0
Console.WriteLine(getINMajorScale(61, 61)); // 1
Console.WriteLine(getINMajorScale(62, 61)); // 3
Console.WriteLine(getINMajorScale(63, 61)); // 5
Console.ReadKey();
}