I am sending some values from a microcontroller to a flutter app in the form of Uint8List then I convert it to. When I send values individually, I have no issue at all. however, when I send 100 values together or any number of values continuously, I get some values correct and others divided in multiple lines. I will be providing a screenshot for the result because its hard to represent it with typing.
This is the code tor receiving:
Future<void> _onDataReceived( Uint8List data ) async {
var fixedList = new List<String>.filled(6, '', growable: true);
// var fixedList1 = <Uint8List>[];
var fixed1 = new List<int>.filled(7, 0, growable: true);
// fixedList1.add(data);
if (data.length >= 7) {
for (int k = 0; k < 7; k++) {
// int x=0;
fixed1[k] = data[k+1];
l++;
}
if (l > 6) {
for (int i = 0; i <= 5; i++) {
fixedList[i] = String.fromCharCode(fixed1[i]);
fixed1[i]=0;
}
l = 0;
fixed1.clear();
print(fixedList); //fixedList1.clear();
}
}
}
Anyone knows what is going on here?
I'm trying to create an audioworklet that loops a single instance of a sound to create a sort of sustain effect. No matter how many sections of the input I loop, I keep hearing a blip type skipping sound. How many calls to the processor is one instance?
To give you an idea, this is what I have so far:
constructor() {
super();
this.sound = [];
this.count = 20;
this.step = [0, 0];
}
process(inputs, outputs, parameters) {
if (inputs && inputs.length) {
for (var i = 0; i < inputs[0].length; i++) {
var input = inputs[0][i];
var output = outputs[0][i];
if (!this.sound[i]) {
this.sound[i] = [];
}
if (this.sound[i].length < this.count) {
this.sound[i].push([]);
for (var j = 0; j < input.length; j++) {
this.sound[i][this.sound[i].length - 1][j] = input[j];
}
} else if (this.sound[i]) {
var s = this.sound[i][this.step[i] % this.sound[i].length];
for (var j = 0; j < s.length; j++) {
output[j] = s[j];
}
this.step[i]++;
}
}
}
return true;
}
So the idea is that I capture the incoming input in an array of N length for each channel(in my case there are 2 channels). Then once that array is full, I cycle through that array to fill the output until the node is disabled.
Thanks for the fiddle. Very helpful.
I didn't look to see what was causing the clicks, but I took your example and modified it very slightly like so:
// #channels 2
// #duration 1.0
// #sampleRate 44100
var bufferSize = 4096;
let ctx = context;
let osc = ctx.createOscillator();
osc.start();
let myPCMProcessingNode = ctx.createScriptProcessor(bufferSize, 2, 2);
let _count = 1;
var sound = [];
var count = _count++;
console.log(count)
var hesitate = 0;
var step = [0, 0];
//Logic to pay attention to
myPCMProcessingNode.onaudioprocess = function(e) {
for(var i = 0; i<2; i++){
var input = e.inputBuffer.getChannelData(i);
var output = e.outputBuffer.getChannelData(i);
if (!sound[i]) {
sound[i] = [];
}
if (sound[i].length < count) {
sound[i].push([]);
for (var j = 0; j < input.length; j++) {
sound[i][sound[i].length - 1][j] = input[j];
}
} else if (sound[i]) {
var s = sound[i][step[i] % sound[i].length];
for (var j = 0; j < s.length; j++) {
output[j] = s[j];
}
step[i]++;
}
}
}
//To hear
osc.connect(myPCMProcessingNode).connect(ctx.destination);
I pasted this in the code window at https://hoch.github.io/canopy. Press the top left button (arrow) to the left of the code window, and you can see the rendered audio. You can see that the output (frequency is 10 instead of 440 to make it easier to see) is discontinuous. This causes the clicks you hear. You can also change the frequency to 100 and find discontinuities in the output.
I hope this is enough to help you figure out what's wrong with your buffering.
An alternative is to create an AudioBufferSourceNode with an AudioBuffer of the basic sample. You can set the AudioBufferSourceNode to loop the whole buffer. This doesn't solve the clicking problem, but it is somewhat simpler.
But this is a general problem of looping any buffer. Unless you arrange the last sample to be close to the first sample, you will hear clicks when you wrap around. You either need to grab chunks where the first and last samples are nearly the same, or modified the chunks so they ramp up at the beginning in some way and ramp down at the end in some way.
I have been using the getEditResponseUrl method for quite some time. However now in the list of over 400 entries some of the urls which are generated end up with a blank form instead of the previously added content. Any idea on solving this?
function linksmaken() {
var urlCol = 64; // kolom nr 64 begint met 1
var responses = form.getResponses();
for (var i = 0; i < responses.length; i++) {
timestamps.push(responses[i].getTimestamp().setMilliseconds(0));
urls.push(responses[i].getEditResponseUrl());
}
for (var j = 1; j < data.length; j++) {
resultUrls.push([data[j][0]?urls[timestamps.indexOf(data[j][0].setMilliseconds(0))]:'']);
}
sheet.getRange(2, urlCol, resultUrls.length).setValues(resultUrls);
}
I have an existing.docx document with some text. All I want is to insert programmatically a table to a specific place. So my idea was to add a Keyword where the table should be inserted. There are no empty lines, before and after the keyword.
After the insertion of the table I add \n, before and after the table, for an empty line but somehow the Xceed library adds three after the table and two before the table.
Here is how I'm doing it:
using (DocX document = DocX.Load(#"C:\Users\rk\Desktop\test.docx"))
{
var IntTableSoftwareLocation = document.FindAll("Table").FirstOrDefault();
document.ReplaceText("Table", "");
var tableSoftware = document.InsertTable(IntTableSoftwareLocation, 3, 5);
tableSoftware.InsertParagraphBeforeSelf("\n");
tableSoftware.InsertParagraphAfterSelf("\n");
tableSoftware.SetBorder(TableBorderType.InsideH, new Border());
tableSoftware.SetBorder(TableBorderType.InsideV, new Border());
tableSoftware.SetBorder(TableBorderType.Left, new Border());
tableSoftware.SetBorder(TableBorderType.Bottom, new Border());
tableSoftware.SetBorder(TableBorderType.Top, new Border());
tableSoftware.SetBorder(TableBorderType.Right, new Border());
//Header
tableSoftware.Rows[0].Cells[0].Paragraphs[0].Append("Col1").Bold().Font("Arial").FontSize(11d);
tableSoftware.Rows[0].Cells[1].Paragraphs[0].Append("Col2").Bold().Font("Arial").FontSize(11d);
tableSoftware.Rows[0].Cells[2].Paragraphs[0].Append("Col3").Bold().Font("Arial").FontSize(11d);
tableSoftware.Rows[0].Cells[3].Paragraphs[0].Append("Col4.").Bold().Font("Arial").FontSize(11d);
tableSoftware.Rows[0].Cells[4].Paragraphs[0].Append("Col5").Bold().Font("Arial").FontSize(11d);
//Content
string TextToInsert = "Some Text";
//Column width
for (int i = 0; i < tableSoftware.RowCount; i++)
{
for (int x = 0; x < tableSoftware.ColumnCount; x++)
{
#region set column width
if (x == 0)
{
tableSoftware.Rows[i].Cells[x].Width = 28.3; // 1cm
}
else if (x == 1)
{
tableSoftware.Rows[i].Cells[x].Width = 318;
}
else if (x == 2)
{
tableSoftware.Rows[i].Cells[x].Width = 50;
}
else if (x == 3)
{
tableSoftware.Rows[i].Cells[x].Width = 28.3;
}
else if (x == 4)
{
tableSoftware.Rows[i].Cells[x].Width = 64;
}
#endregion
}
}
tableSoftware.Rows[2].Cells[1].Paragraphs[0].Append(TextToInsert + "\n").FontSize(11d).Bold().Font("Arial");
tableSoftware.Rows[2].Cells[2].Paragraphs[0].Append("User").Font("Arial").Alignment = Alignment.center;
tableSoftware.Rows[2].Cells[2].VerticalAlignment = VerticalAlignment.Center;
tableSoftware.Rows[2].Cells[3].Paragraphs[0].Append("1").Font("Arial").Alignment = Alignment.center;
tableSoftware.Rows[2].Cells[3].VerticalAlignment = VerticalAlignment.Center;
tableSoftware.Rows[2].Cells[4].Paragraphs[0].Append("2.199,00 €").Font("Arial").Alignment = Alignment.right;
tableSoftware.Rows[2].Cells[4].VerticalAlignment = VerticalAlignment.Center;
document.Save();
}
And thats how my docx Document looks like:
laksjdf
Table
alskdfjs
Ok, this is how it should be done:
//Find the Paragraph by keyword
var paraTable = document.Paragraphs.FirstOrDefault(x => x.Text.Contains("Table"));
// Remove the Keyword
paraTable.RemoveText(0);
//Insert the table into Paragraph
var table = paraTable.InsertTableAfterSelf(3, 5);
No strange empty lines anymore
When I use an Area Chart on Google Drive, I can select an option to "Switch Rows / Columns".
Now that I am playing with the Javascript API, I'd like to do the same but couldn't find a way to do it in the documentation.
Here's the code I am using successfully. All I need is to switch row/column on the API.
<script type="text/javascript">
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['data',0,1,2,3,4,5,6]
,['2013-04-14 (336)',064,04,03,02,06,02,02]
,['2013-04-21 (169)',0,028,03,02,04,02,02]
,['2013-04-28 (121)',0,0,027,02,01,02,02]
,['2013-05-05 (101)',0,0,0,020,0,01,0]
,['2013-05-12 (688)',0,0,0,0,0143,017,07]
,['2013-05-19 (3226)',0,0,0,0,0,0642,022]
,['2013-05-26 (321)',0,0,0,0,0,0,082]
]);
var options = {
title: 'Company Performance', isStacked:true,
hAxis: {title: 'Year', titleTextStyle: {color: 'red'}}
};
var chart = new google.visualization.AreaChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
</script>
Can anyone help?
Unfortunately you have to transpose the DataTable. The following code will do the job. If anyone can improve it, please share improved version.
This function would work passing a DataView as well.
In your case: var transposedData = transposeDataTable(data);
function transposeDataTable(dataTable) {
//step 1: let us get what the columns would be
var rows = [];//the row tip becomes the column header and the rest become
for (var rowIdx=0; rowIdx < dataTable.getNumberOfRows(); rowIdx++) {
var rowData = [];
for( var colIdx = 0; colIdx < dataTable.getNumberOfColumns(); colIdx++) {
rowData.push(dataTable.getValue(rowIdx, colIdx));
}
rows.push( rowData);
}
var newTB = new google.visualization.DataTable();
newTB.addColumn('string', dataTable.getColumnLabel(0));
newTB.addRows(dataTable.getNumberOfColumns()-1);
var colIdx = 1;
for(var idx=0; idx < (dataTable.getNumberOfColumns() -1);idx++) {
var colLabel = dataTable.getColumnLabel(colIdx);
newTB.setValue(idx, 0, colLabel);
colIdx++;
}
for (var i=0; i< rows.length; i++) {
var rowData = rows[i];
console.log(rowData[0]);
newTB.addColumn('number',rowData[0]); //assuming the first one is always a header
var localRowIdx = 0;
for(var j=1; j< rowData.length; j++) {
newTB.setValue(localRowIdx, (i+1), rowData[j]);
localRowIdx++;
}
}
return newTB;
}
Source and credit:
http://captaindanko.blogspot.sg/2013/05/transpose-of-google-visualization-data.html
Example:
https://bitbucket.org/cptdanko/blog-code/src/0666cdce533db48cd89a4e2f02ef7e87a891c857/transpose.html?at=default
A neater and more efficient version with use of the getDate function on the first column label.
Here's a nice and verbose edition commented to explain what's going on -
function transposeDateDataTable (dataTable) {
// Create new datatable
var newDataTable = new google.visualization.DataTable ();
// Add first column from original datatable
newDataTable.addColumn ('string', dataTable.getColumnLabel (0));
// Convert column labels to row labels
for (var x=1; x < dataTable.getNumberOfColumns (); x++) {
var label = dataTable.getColumnLabel (x);
newDataTable.addRow ([label]);
}
// Convert row labels and data to columns
for (var x=0; x < dataTable.getNumberOfRows (); x++) {
newDataTable.addColumn ('number', dataTable.getValue (x, 0).getDate ()); // Use first column date as label
for (var y=1; y < dataTable.getNumberOfColumns (); y++) {
newDataTable.setValue (y-1, x+1, dataTable.getValue (x, y));
}
}
return newDataTable;
}
Or the nice and compact version...
function transposeDateDataTable (dt) {
var ndt = new google.visualization.DataTable;
ndt.addColumn ('string',dt.getColumnLabel(0));
for (var x=1; x<dt.getNumberOfColumns(); x++)
ndt.addRow ([dt.getColumnLabel(x)]);
for (var x=0; x<dt.getNumberOfRows(); x++) {
ndt.addColumn ('number', dt.getValue(x,0).getDate());
for (var y=1; y<dt.getNumberOfColumns(); y++)
ndt.setValue (y-1, x+1, dt.getValue (x,y));
}
return ndt;
}