Imagine this function:
void SoundManager::playSource(ALuint sourceID, float offset)
{
alSourceStop(sourceID);
ALint iTotal = 0;
ALint iCurrent = 0;
ALint uiBuffer = 0;
alGetSourcei(sourceID, AL_BUFFER, &uiBuffer);
alGetBufferi(uiBuffer, AL_SIZE, &iTotal);
iCurrent = iTotal * offset;
alSourcei(sourceID, AL_BYTE_OFFSET, iCurrent);
alSourcePlay(sourceID);
}
The idea is calling playSource(x, 0.5f) would jump to (roughly) halfway through the buffer, etc.
It works fine the first time I call it, but if I call it again on the same source (whether that source is playing or not) it begins playing as though I'd called it with offset 0.
Any ideas why?
Solved!
Even though the API claims that setting the offsets works on sources in any state, the problem was I should have been calling alSourceRewind instead of alSourceStop at the start.
It seems setting offsets only works on sources in the AL_INITIAL state.
you can play the audio file first,then call setOffset like this,don't need to call alSourcePlay:
- (BOOL)setOffset:(float)offset
{
ALint iTotal = 0;
ALint iCurrent = 0;
ALint uiBuffer = 0;
alGetSourcei(_sourceID, AL_BUFFER, &uiBuffer);
alGetBufferi(uiBuffer, AL_SIZE, &iTotal);
iCurrent = iTotal * offset;
alSourcei(_sourceID, AL_BYTE_OFFSET, iCurrent);
return ((_error = alGetError()) != AL_NO_ERROR);
}
Related
I am trying to make an old TV static type effect in P5.js, and although I am able to make the effect work, the frame rate is quite low.
My approach is the following:
Loop through each pixel
Set the stroke to a random value
Call the point() function to paint the pixel
Initially, I was doing this in the draw function directly but it was very slow. I was getting less than 1 frame a second. So I switch to the following paint buffer approach:
const SCREEN_WIDTH = 480
const SCREEN_HEIGHT = 480
var ScreenBuffer;
function setup(){
createCanvas(SCREEN_WIDTH, SCREEN_HEIGHT);
ScreenBuffer = createGraphics(SCREEN_WIDTH,SCREEN_HEIGHT);
}
function draw(){
paintBuffer();
image(ScreenBuffer,0,0);
}
function paintBuffer(){
console.log("Painting Buffer")
for(var x = 0; x< SCREEN_WIDTH; x++){
for(var y = 0; y< SCREEN_HEIGHT; y++){
ScreenBuffer.stroke(Math.random() * 255)
ScreenBuffer.point(x,y)
}
}
}
Although I am getting a performance improvement, its nowhere near the 30 frames a second I want to be at. Is there a better way to do this?
The only way I can get reasonable performance is by filling up the screen with small squares instead with the following code:
for(var x = 0; x< SCREEN_WIDTH-10; x+=10){
for(var y = 0; y< SCREEN_HEIGHT-10; y+=10){
//ScreenBuffer.stroke(Math.random() * 255)
//ScreenBuffer.point(x,y)
ScreenBuffer.fill(Math.random() * 255);
ScreenBuffer.noStroke()
ScreenBuffer.rect(x,y,10,10)
}
}
But I would really like a pixel effect - ideally to fill the whole screen.
Believe it or not, it's actually the call to stroke() that's slowing down your sketch. You can get around this by setting the value of the pixels directly, using the set() function or accessing the pixels array directly.
More info can be found in the reference, but here's a simple example:
function setup() {
createCanvas(500, 500);
}
function draw() {
for (var i = 0; i < width; i++) {
for (var j = 0; j < height; j++) {
var c = random(255);
set(i, j, c);
}
}
updatePixels();
text(frameRate(), 20, 20);
}
Another approach you might consider is generating a few buffers that contain static images ahead of time, and then using those to draw your static. There's really no need to make the static completely dynamic, so do the work once and then just load from image files or buffers created using the createGraphics() function.
I found this post online (dates back to 2013) when I had trouble getting direct access to a specific cell in a vtkPolyData. I am using the latest version: VTK 8.1.1 and it seems like the newer version of VTK still has this issue.
polys->InitTraversal();
for(int i = 0; i < polys->GetNumberOfCells(); i++)
{
polys->GetNextCell(idList); // This sequential method gets the point IDs correctly
int a = idList->GetId(0);
int b = idList->GetId(1);
int c = idList->GetId(2);
}
However, the direct access method seems to have issues
polys->InitTraversal();
for(int i = 0; i < polys->GetNumberOfCells(); i++)
{
polys->GetCell(i, idList); // This method returns wrong ids
int a = idList->GetId(0);
int b = idList->GetId(1);
int c = idList->GetId(2);
}
How can I get the point IDs in a specific cell without looping through all the cell? Isn't polys->GetCell(i, idList) meant to give you direct access to a specific cell?
For direct access, we can use vtkPolyData::GetCellPoints() method. For example we can do
vtkNew<vtkIdList> idL; // or auto idL = vtkSmartPointer<vtkIdList>::New();
poly->GetCellPoints( 13, idL ); // Assuming you want the points for 13th cell
for(auto i = 0; i < idL->GetNumberOfIds(); ++i)
std::cout<< idL->GetId(i) << std::endl;
For looping over all cells I prefer a while loop:
vtkNew<vtkIdList> idL;
poly->GetPolys()->InitTraversal();
while(poly->GetPolys()->GetNextCell(idL)){
for(auto i = 0; i < idL->GetNumberOfIds(); ++i)
std::cout<< idL->GetId(i) << std::endl;
}
I'm trying to write my first real program with dynamic arrays, but I've come across a problem I cannot understand. Basically, I am trying to take a dynamic array, copy it into a temporary one, add one more address to the original array, then copy everything back to the original array. Now the original array has one more address than before. This worked perfectly when trying with ints, but strings crash my program. Here's an example of the code I'm struggling with:
void main()
{
int x = 3;
std::string *q;
q = new std::string[x];
q[0] = "1";
q[1] = "2";
q[2] = "3";
x++;
std::string *temp = q;
q = new std::string[x];
q = temp;
q[x-1] = "4";
for (int i = 0; i < 5; i++)
std::cout << q[i] << std::endl;
}
If I were to make q and temp into pointers to int instead of string then the program runs just fine. Any help would be greatly appreciated, I've been stuck on this for an hour or two.
q = temp performs only a shallow copy. You lose the original q and all of the strings it pointed to.
Since you reallocated q to have 4 elements, but then immediately reassigned temp (which was allocated with only 3 elements), accessing (and assigning) the element at x now is outside the bounds of the array.
If you have to do it this way for some reason, it should look like this:
auto temp = q;
q = new std::string[x];
for(int x = 0; x < 3; ++x)
q[x] = temp[x];
delete [] temp;
q[x] = 4;
However, this is obviously more complex and very much more prone to error than the idiomatic way of doing this in C++. Better to use std::vector<std::string> instead.
I am trying to calculate row count from a large file based on presence of a certain character and would like to use StreamReader and ReadBlock - below is my code.
protected virtual long CalculateRowCount(FileStream inStream, int bufferSize)
{
long rowCount=0;
String line;
inStream.Position = 0;
TextReader reader = new StreamReader(inStream);
char[] block = new char[4096];
const int blockSize = 4096;
int indexer = 0;
int charsRead = 0;
long numberOfLines = 0;
int count = 1;
do
{
charsRead = reader.ReadBlock(block, indexer, block.Length * count);
indexer += blockSize ;
numberOfLines = numberOfLines + string.Join("", block).Split(new string[] { "&ENDE" }, StringSplitOptions.None).Length;
count ++;
} while (charsRead == block.Length);//charsRead !=0
reader.Close();
fileRowCount = rowCount;
return rowCount;
}
But I get error
Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.
I am not sure what is wrong... Can you help. Thanks ahead!
For one, read the StreamReader.ReadBlock() documentation carefully http://msdn.microsoft.com/en-us/library/system.io.streamreader.readblock.aspx and compare with what you're doing:
The 2nd argument (indexer) should be within the range of the block you're passing in, but you're passing something that will probably exceed it after one iteration. Since it looks like you want to reuse the memory block, pass 0 here.
The 3rd argument (count) indicates how many bytes to read into your memory block; passing something larger than the block size might not work (depends on implementation)
ReadBlock() returns the number of bytes actually read, but you increment indexer as if it will always return the size of the block exactly (most of the time, it won't)
There was a task to know which code is faster and why:
//A
Stopwatch sw = new Stopwatch();
Int32[] a = new Int32[10000000];
int len = a.Length;
sw.Start();
//for (Int32 index = 0; index < len; index++)
//{
// a[index] = 6;
//}
//sw.Stop();
//B
for (Int32 index = 0; index < a.Length; index++)
{
a[index] = 6;
}
sw.Stop();
var time = sw.ElapsedMilliseconds;
The avarage time of approach B is little more than A. Does anybody explain why?
My guess would be because you are polling the length of the array each time you loop, whereas the A approach only has to check a cached value of the length. So, ultimately, this comes down to the idea of caching
In case B, each time through the loop, runtime is calling code to get the length of the array.
In A, this is done once and the result saved.
I've always thought that the runtime would optimize that loop and they would be the same. Are your results significantly different? Have you run the test a few time to see that it is consistently different?