Exemple #1
0
void Session::bounce_region(RegionPtr region, std::string filename, Session::FileType type){
  
	//use the bounce session to create file
	//e.g Session temp;
	//add the region 
	//temp->add_region(region)
	//bounce down
	//temp->bounce_session(filename)
	//change original region to the new soundfile.
	SamplePosition storedPosition = region->get_start_pos();
	Session temp;
	temp.set_playback_duration(region->get_duration() + region->get_extension());
	region->set_start_pos(0);
	temp.add_region(region);
	temp.bounce_session(filename,type);
	region->set_start_pos(storedPosition);
}
Exemple #2
0
void Session::remove_region(RegionPtr region){
  	ScopedMutexLock lock(m_audioMutex);
// 	assert(region && "Remove Region: RegionPtr Invalid");
	
// 	assert(std::find(m_regionPlaylist.begin(), m_regionPlaylist.end(), region) != m_regionPlaylist.end()) ;
	if(!region)throw "Region invalid";
	if(std::find(m_regionPlaylist.begin(),m_regionPlaylist.end(),region) == m_regionPlaylist.end() )throw "Could not find region";
	m_regionPlaylist.remove(region);
	region.reset();
}
Exemple #3
0
void OGRLIBKMLLayer::Finalize(DocumentPtr poKmlDocument)
{
    KmlFactory *poKmlFactory = m_poOgrDS->GetKmlFactory (  );

    if( m_bWriteRegion && m_dfRegionMinX < m_dfRegionMaxX )
    {
        RegionPtr region = poKmlFactory->CreateRegion();

        LatLonAltBoxPtr box = poKmlFactory->CreateLatLonAltBox();
        box->set_west(m_dfRegionMinX);
        box->set_east(m_dfRegionMaxX);
        box->set_south(m_dfRegionMinY);
        box->set_north(m_dfRegionMaxY);
        region->set_latlonaltbox(box);

        LodPtr lod = poKmlFactory->CreateLod();
        lod->set_minlodpixels(m_dfRegionMinLodPixels);
        lod->set_maxlodpixels(m_dfRegionMaxLodPixels);
        if( (m_dfRegionMinFadeExtent != 0 || m_dfRegionMaxFadeExtent != 0) &&
            m_dfRegionMinFadeExtent + m_dfRegionMaxFadeExtent <
                m_dfRegionMaxLodPixels - m_dfRegionMinLodPixels )
        {
            lod->set_minfadeextent(m_dfRegionMinFadeExtent);
            lod->set_maxfadeextent(m_dfRegionMaxFadeExtent);
        }

        region->set_lod(lod);
        m_poKmlLayer->set_region(region);
    }

    createkmlliststyle (poKmlFactory,
                        GetName(),
                        m_poKmlLayer,
                        poKmlDocument,
                        osListStyleType,
                        osListStyleIconHref);
}
Exemple #4
0
std::string Session::timestretch_region(RegionPtr region, double speed, std::string folderpath, std::string name, int fftSize, int numOverlaps){
  //got here
  //need to take region,
  //call internal process on the region passing the output into a table,
  //run through the table with phasor set up accordingly 
  //render out the new region using sndfile
  
  //initially use the table lookup functionality
  
  
  fsom::DebugStream << "Entering Timestretch"<<std::endl;
  ///////////////////////////////////////////////////////
  ////////Create new session with the region/////////////
  SamplePosition storedPosition = region->get_start_pos();
  Session temp;
  temp.set_playback_duration(region->get_duration() + region->get_extension());
  region->set_start_pos(0);
  temp.add_region(region);
  std::string filepath = folderpath + name+"bounce.wav";
  temp.bounce_session(filepath);
  region->set_start_pos(storedPosition);
  fsom::DebugStream << "Region Bounced"<<std::endl;
  ///////////////////////////////////////////////////////
  ///////

   std::stringstream ssPath;
   char number[24]; // dummy size, you should take care of the size!
//    sprintf(number, "%.2f", stretchAmount);
   
  ssPath<<  folderpath<<  "TS"  << name<< (1.0f/speed)*100<<"%.wav";
  
  TimeStretcher timeStretcher(speed,fftSize,numOverlaps,filepath,ssPath.str() );
  timeStretcher.run();
  /*
  MultiTableBuffer t_tables=load_file_to_table(filepath);
  fsom::DebugStream << "File loaded into table"<<std::endl;
  std::stringstream ssPath;
  ssPath<<  folderpath<< name<<stretchAmount*100<< "%TStretch.wav";
  SNDFILE* outfile;
  SF_INFO m_info;
  m_info.channels = 2;
  m_info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16 | SF_ENDIAN_LITTLE;
  m_info.samplerate = 44100;
  outfile = sf_open(ssPath.str().c_str(),SFM_WRITE,&m_info);
  
  fsom::DebugStream << "Table size =  "<< t_tables.at(0)->get_size()+1  ;
  
  
  //FIXME mixing logic here!!!!!!
  
  /*
  Phasor t_phasor(44100,stretchAmount/2.0f);
  float* tempBuf = new float[2];
  for(int n = 0; n < float(region->get_duration()/2)*stretchAmount ;++n){
	      tempBuf[0]= t_tables.at(0)->linear_lookup(t_phasor.get_phase()*(t_tables.at(0)->get_size()+1));
	      tempBuf[1]= t_tables.at(1)->linear_lookup(t_phasor.get_phase()*(t_tables.at(1)->get_size()+1));
	      sf_writef_float(outfile,tempBuf,2);//write to disk
	      t_phasor.tick();
  }
  delete []tempBuf;
  
  
 
  const int HEADCOUNT = 16;
  const int WINDOWSIZE = 1024;
  const float FREQ = 44100.0f/float(WINDOWSIZE);
  Phasor tapeHead(44100,FREQ);
  Table<double> t_han(WINDOWSIZE);
  t_han.fill_hann();
  
  float pos = 0.0;
  
  float rate = 1.0f/stretchAmount;
  
  float headPos[HEADCOUNT];
  for(int n = 0; n < HEADCOUNT; ++n){
    headPos[n] = 0;
  }
  
  int size = region->get_duration()/rate;
  for(int samp = 0; samp < size;++samp){
  
	float s[2];
	s[0] = s[1] = 0.0f;
	
	
	
	for(int n = 0; n < HEADCOUNT; ++n){
	    float phase = phase_wrap(  tapeHead.get_phase() + float(n)/float(HEADCOUNT)    );      
	    float gain = t_han.linear_lookup(phase*float(WINDOWSIZE))      ;
	    
	    
	    if( phase < 0.001 ){
	      headPos[n] = pos;
	    }
	      
	    s[0] += ( t_tables.at(0)->linear_lookup( phase*float(WINDOWSIZE) + headPos[n]   ) * gain) * (1.0f/float(HEADCOUNT));
	    s[1] += ( t_tables.at(1)->linear_lookup( phase*float(WINDOWSIZE) + headPos[n]   ) * gain )* (1.0f/float(HEADCOUNT));
	}
	
	tapeHead.tick();
	
	sf_writef_float(outfile,s,1);//write to disk
	
	pos += rate;
  }
  
  */
  
  
  
  return ssPath.str();
  //////////////////////////////////////////////////////
  ///////
  
  
}
Exemple #5
0
	bool operator()(const RegionPtr& lhs, const RegionPtr& rhs){
		if(lhs->get_start_pos() == rhs->get_start_pos()) return lhs->get_duration() < rhs->get_duration();
		return lhs->get_start_pos() < rhs->get_start_pos();
	}
Exemple #6
0
RegionPtr Session::create_region_from_node(TiXmlElement* element){
  assert(element);
  TiXmlElement * basicInfoElement = element->FirstChildElement("BasicInfo");
  assert(basicInfoElement);
  int start = 0;
  basicInfoElement->QueryIntAttribute("start", &start);
  int duration = 0;
  
  basicInfoElement->QueryIntAttribute("duration", &duration);
  int offset = 0;
  basicInfoElement->QueryIntAttribute("offset", &offset);
  int lanenum = 0;
  
  basicInfoElement->QueryIntAttribute("lanenum", &lanenum);
	int extension = 0;
  basicInfoElement->QueryIntAttribute("extension", &extension);
 
  int reverseState =0;
  basicInfoElement->QueryIntAttribute("reversestate",&reverseState);
  
  int muteState = 0;
  basicInfoElement->QueryIntAttribute("mutestate",&muteState);

  std::string path = basicInfoElement->Attribute("path");
   fsom::DebugStream << "Loading, working directory = "<< m_workingDirectory<<std::endl;
  regionCreationStruct cs(start, duration,offset,lanenum,extension, path,m_workingDirectory,bool(reverseState));
  
  TiXmlElement * meta = element->FirstChildElement("MetaData");

  RegionPtr pRegion = RegionManager::get_instance().create(meta->Attribute("RegionType"),cs);
  pRegion->set_mute_state(muteState);
  assert(pRegion);
  
  load_region_parameters(element,pRegion.get());
  
  pRegion->register_meta("RegionType");
  pRegion->register_meta("Tip");

  pRegion->set_meta("RegionType", meta->Attribute("RegionType"));
  pRegion->set_meta("Tip", meta->Attribute("Tip"));
  
  std::string image = meta->Attribute("image");
  std::string managerId = meta->Attribute("managerId");
  pRegion->register_meta("image");
  pRegion->register_meta("managerId");
  pRegion->set_meta("image",image);
  pRegion->set_meta("managerId",managerId);

   fsom::DebugStream << "Metadata read, image = " <<image<<std::endl;
  
  
  
  TiXmlElement * effectChild = element->FirstChildElement("Effect");
  
  while(effectChild){
    
	DSPEffectPtr e = create_effect_from_node(effectChild,pRegion.get());
	pRegion->attach_effect(e);
	effectChild = effectChild->NextSiblingElement("Effect");

  }
  
   fsom::DebugStream  << "Loaded region:" << path << std::endl;
  
  if(pRegion->get_meta("RegionType") == std::string("AdditiveSynthesis")){
       fsom::DebugStream << "Synthesis region found"<<std::endl;
      SynthesisRegionPtr synthregion = boost::dynamic_pointer_cast<fsom::SynthesisRegion>(pRegion); 
      //Remove the automatic generators
      synthregion->remove_all_generators();
      //remove the automatic modules
      synthregion->remove_all_modules();
      
      TiXmlElement* generatorElement = element->FirstChildElement("Generator");
      while(generatorElement){
	GeneratorPtr gen = create_generator_from_node(generatorElement,pRegion.get());
	synthregion->add_generatorPtr(gen);
	generatorElement = generatorElement->NextSiblingElement("Generator");
      }
       fsom::DebugStream << "No of generators spawned =  "<< synthregion->get_generator_stack().size()<<std::endl;
      TiXmlElement* moduleElement = element->FirstChildElement("Module");
      while(moduleElement){
	SynthesisModulePtr mod = create_module_from_node(moduleElement,pRegion.get());
	synthregion->add_modulePtr(mod);
	moduleElement = moduleElement->NextSiblingElement("Module");
      }
//       pRegion = synthregion;
  }else if(pRegion->get_meta("RegionType")==std::string("GranularSynthesis") ){
      boost::shared_ptr<fsom::GranularRegion> gran_region = boost::dynamic_pointer_cast<fsom::GranularRegion>(pRegion);
      if(!path.empty()){
	gran_region->load_soundfile( m_workingDirectory + path );
      }else{
	gran_region->fill_table_sin();  
      }
  }
  
  
  
  
  return RegionPtr(pRegion);
}
int main(int argc, char** argv) {
    if (argc < 2) {
        std::cout << "Usage: <executable> #of_iterations" << std::endl;
        exit(EXIT_FAILURE);
    }
    utils::rnd::init(2039281);
    const int maxiter = std::atoi(argv[1]);
    StridedIntervalPtr limits = StridedInterval::get(0,100000,1);
    RegionPtr r2 = RegionTy::getFresh(rg::WEAK_HEAP, limits);
    
    ValSet::VSetPtr bot = ValSet::getBot();
    ValSet::VSetPtr top = ValSet::getTop();
    std::cout << *bot << " " << *top << std::endl;
    StridedIntervalPtr sitop = StridedInterval::getTop();
    StridedIntervalPtr sibot = StridedInterval::getBot();
    StridedIntervalPtr adr1 = StridedInterval::get(100000,100004,4);

    RegionPtr r0 = RegionTy::getFresh();
    RegionPtr r1 = RegionTy::getFresh(rg::STRONG_HEAP, limits);
    RegionPtr r3 = RegionTy::getFresh(rg::STRONG_STACK,limits);

    // T0: Subsumption checks
    assert(adr1->subsumes(*sibot) && "Bot not subsumed?");
    assert(!sibot->subsumes(*adr1) && "Bot subsumes something else?");
    assert(sitop->subsumes(*adr1) && 
            "Top doesn't subsume something else?");
    assert(sitop->subsumes(*sibot) && "Top doesn't subsume bot?");
    assert(!sibot->subsumes(*sitop) && "Bot subsumes top?");
    assert(!adr1->subsumes(*sitop) && "Something else subsumes top?");

    // T1: read/write out of bounds
    VSetPtr res1 = r1->read(adr1);
    assert(!res1.get() && "Unexpected result of read out of bounds.");
    RegionPtr r = r1->write(adr1, top);
    assert(r == r1 && "Unexpected result of write out of bounds.");

    // T2: double read/write to the same location with different values
    StridedIntervalPtr adr2 = StridedInterval::get(4,20,4);
    StridedIntervalPtr adr3 = StridedInterval::get(24,32,2);
    StridedIntervalPtr cns1 = StridedInterval::get(5,6,1);
    StridedIntervalPtr cns2 = StridedInterval::get(2,10,2);
    StridedIntervalPtr cns3 = StridedInterval::get(24,60,4);
    StridedIntervalPtr rng1 = StridedInterval::get(6,13,1);
    r = r->write(adr2, std::make_pair(r0,cns1));
    r = r->write(adr2, std::make_pair(r0,cns1));
    std::cout << *r << std::endl;

    // T3: double write to the same address
    r = r->write(adr3, std::make_pair(r1,rng1));
    r = r->write(adr3, std::make_pair(r1,rng1));
    std::cout << *r << std::endl;

    // T4: read followed by write returns the same result
    //utils::Cmp<ContentPair> cmp;
    VSetPtr vsp1 = r->read(adr3);
    assert(*vsp1 == *ValSet::get(std::make_pair(r1,rng1))
            && "Unexpected value read back.");

    // T5: operations on valsets
    StridedIntervalPtr si1 = StridedInterval::get(40,48,4);
    VSetPtr vsp2 = vsp1->insert(std::make_pair(r3,si1));
    assert(*vsp2->erase(std::make_pair(r3,si1)) == *vsp1 &&
            "Unexpected result of erase.");
    assert(vsp2->subsumes(*vsp1) && "Unexpected result.");
    assert(vsp1->subsumedBy(*vsp2) && "Unexpected result.");
    // Note that adding a non-multiple of stride will cause problems,
    // that's fine.
    VSetPtr vsp3 = *vsp2 + 4;
    std::cout << "Before: " << *vsp2 << std::endl;
    std::cout << "After+: " << *vsp3 << std::endl;
    VSetPtr vsp4 = vsp2->meet(*vsp3);
    VSetPtr vsp5 = vsp2->join(*vsp3);
    VSetPtr vsp6 = vsp2->widen(*vsp3);
    std::cout << "Meet: " << *vsp4 << std::endl;
    std::cout << "Join: " << *vsp5 << std::endl;
    std::cout << "Widen: " << *vsp6 << std::endl;
    VSetPtr vsp7 = *vsp2 | *vsp3;
    VSetPtr vsp8 = *vsp2 & *vsp3;
    VSetPtr vsp9 = *vsp2 ^ *vsp3;
    std::cout << "OR : " << *vsp7 << std::endl;
    std::cout << "AND: " << *vsp8 << std::endl;
    std::cout << "XOR: " << *vsp9 << std::endl;
    VSetPtr vsp10 = ValSet::get(std::make_pair(r0,cns1));
    VSetPtr vsp11 = *vsp2 | *vsp10;
    VSetPtr vsp12 = *vsp2 & *vsp10;
    VSetPtr vsp13 = *vsp2 ^ *vsp10;
    std::cout << "--- " << *vsp2 << " , " << *vsp10 << " ---" <<
        std::endl;
    std::cout << "OR : " << *vsp11 << std::endl;
    std::cout << "AND: " << *vsp12 << std::endl;
    std::cout << "XOR: " << *vsp13 << std::endl;
    std::cout << *(*vsp11 + *vsp10) << std::endl;
    std::cout << *(*vsp12 - *vsp10) << std::endl;

    // T6: operations on TOP/BOT
    std::cout << "------- BOT:BOT ---------" << std::endl;
    std::cout << *(*bot - *bot) << std::endl;
    std::cout << *(*bot + *bot) << std::endl;
    std::cout << *(*bot | *bot) << std::endl;
    std::cout << *(*bot & *bot) << std::endl; 
    std::cout << *(*bot ^ *bot) << std::endl; 
    std::cout << *bot->join(*bot) << std::endl;
    std::cout << *bot->meet(*bot) << std::endl; 
    std::cout << *bot->widen(*bot) << std::endl;

    std::cout << "------- BOT:TOP ---------" << std::endl;
    std::cout << *(*bot - *top) << std::endl;  // TOP
    std::cout << *(*bot + *top) << std::endl;  // TOP
    std::cout << *(*bot | *top) << std::endl;  // TOP
    std::cout << *(*bot & *top) << std::endl;  // BOT
    std::cout << *(*bot ^ *top) << std::endl;  // TOP
    std::cout << *bot->join(*top) << std::endl; // TOP
    std::cout << *bot->meet(*top) << std::endl; // BOT
    std::cout << *bot->widen(*top) << std::endl;// TOP

    std::cout << "------- TOP:BOT ---------" << std::endl;
    std::cout << *(*top - *bot) << std::endl; // TOP
    std::cout << *(*top + *bot) << std::endl; // TOP
    std::cout << *(*top | *bot) << std::endl; // TOP
    std::cout << *(*top & *bot) << std::endl; // BOT
    std::cout << *(*top ^ *bot) << std::endl; // TOP
    std::cout << *top->join(*bot) << std::endl;// TOP
    std::cout << *top->meet(*bot) << std::endl;// BOT
    std::cout << *top->widen(*bot) << std::endl;//BOT

    std::cout << "------- TOP:TOP ---------" << std::endl;
    std::cout << *(*top - *top) << std::endl;
    std::cout << *(*top + *top) << std::endl;
    std::cout << *(*top | *top) << std::endl;
    std::cout << *(*top & *top) << std::endl;
    std::cout << *(*top ^ *top) << std::endl;
    std::cout << *top->join(*top) << std::endl;
    std::cout << *top->meet(*top) << std::endl;
    std::cout << *top->widen(*top) << std::endl;

    // T7: reading/writing TOP/BOT
    r = r->write(sitop, std::make_pair(r1,rng1));
    r = r->write(sibot, std::make_pair(r1,rng1));
    vsp1 = r->read(sitop);
    vsp1 = r->read(sibot);
    
    // T8: misaligned reads/writes
    std::cout << "--- Misaligned reads/writes ---" << std::endl;
    StridedIntervalPtr si2 = StridedInterval::get(40,80,4);
    StridedIntervalPtr si3 = StridedInterval::get(34,46,2);
    StridedIntervalPtr si4 = StridedInterval::get(48,58,2);
    StridedIntervalPtr si5 = StridedInterval::get(43,51,1);
    StridedIntervalPtr si6 = StridedInterval::get(32,64,4);
    StridedIntervalPtr si7 = StridedInterval::get(32,64,4);
    std::cout << "    " << *r << std::endl;

    RegionPtr rp = r->write(si2, std::make_pair(r1, cns2));
    std::cout << "#######################################" << std::endl;
    std::cout << "W1: " << *rp << std::endl;
    RegionPtr r4 = rp->write(si3, std::make_pair(r2, cns2));
    std::cout << "W2: " << *r4 << std::endl;
    std::cout << "#######################################" << std::endl;
    std::cout << "W1: " << *rp << std::endl;
    RegionPtr r5 = rp->write(si4, std::make_pair(r2, cns2));
    std::cout << "W3: " << *r5 << std::endl;
    std::cout << "#######################################" << std::endl;
    std::cout << "W1: " << *rp << std::endl;
    RegionPtr r6 = rp->write(si5, std::make_pair(r2, cns2));
    std::cout << "W3: " << *r6 << std::endl;
    std::cout << "#######################################" << std::endl;
    RegionPtr rr = r->write(si3, std::make_pair(r4, cns3));
    rr = rr->write(si4, std::make_pair(r2, cns2));
    std::cout << "W3: " << *rr << std::endl;
    RegionPtr r7 = rr->write(si5, std::make_pair(r2, cns2));
    std::cout << "W4: " << *r7 << std::endl;
    std::cout << "#######################################" << std::endl;
    std::cout << "W4: " << *rr << std::endl;
    RegionPtr r8 = rr->write(si7, std::make_pair(r1,cns3));
    std::cout << "W5: " << *r8 << std::endl;
    std::cout << "#######################################" << std::endl;
    StridedIntervalPtr si8 = StridedInterval::get(64,80,8);
    StridedIntervalPtr si9 = StridedInterval::get(83,87,1);
    StridedIntervalPtr si10 = StridedInterval::get(88,100,4);
    StridedIntervalPtr si11 = StridedInterval::get(52,90,2);
    std::cout << "W5: " << *rr << std::endl;
    RegionPtr r9 = rr->write(si8, std::make_pair(r0,cns1));
    RegionPtr r10 = r9->write(si9, std::make_pair(r2,cns2));
    RegionPtr r11 = r10->write(si10, std::make_pair(r3,cns3));
    std::cout << "W6: " << *r11 << std::endl;
    RegionPtr r12 = r10->write(si11, std::make_pair(r1,adr2));
    std::cout << "W7: " << *r12 << std::endl;
    RegionPtr r13 = r10->getWeaklyUpdatable();
    RegionPtr r14 = r13->write(si11, std::make_pair(r1,cns3));
    std::cout << "W8: " << *r14 << std::endl;

    // T9: performance stress test
    StridedIntervalPtr si12, si13;
    RegionPtr r15 = RegionTy::getFresh(rg::STRONG_HEAP);
    RegionPtr r16 = RegionTy::getFresh(rg::WEAK_HEAP);
    for (int i = 0; i < maxiter; i++) {
skip_zero_stride:
        si13 = StridedInterval::getRand(RNDLIMIT, STRDLIMIT);
        si12 = StridedInterval::getRand(RNDLIMIT, STRDLIMIT);
        if (si12->getStride() == 0) {
            goto skip_zero_stride;
        }
        if (!RegionTy::checkWrite(si12, std::make_pair(r2,si13))) {
            goto skip_zero_stride;
        }
        r15 = r15->write(si12, std::make_pair(r2, si13));
        if (i+1==maxiter) {
            std::cout << "Fragments: " << r15->getSize() << std::endl;
        }
        r16 = r16->write(si12, std::make_pair(r2, si13));
    }

    // Test of deallocation (run with valgrind, it should report 0
    // leaks)
    RegionTy::shutdown();
    ValSet::shutdown();
    StridedInterval::shutdown();
    utils::rnd::shutdown();
};
Exemple #8
0
void BiomeView::drawChunk(int a_ChunkX, int a_ChunkZ)
{
	if (!hasData())
	{
		return;
	}

	// Fetch the region:
	int regionX;
	int regionZ;
	Region::chunkToRegion(a_ChunkX, a_ChunkZ, regionX, regionZ);
	RegionPtr region = m_Cache.fetch(regionX, regionZ);

	// Figure out where on the screen this chunk should be drawn:
	// first find the center chunk
	int centerchunkx = floor(m_X / 16);
	int centerchunkz = floor(m_Z / 16);
	// and the center chunk screen coordinates
	int centerx = m_Image.width()  / 2;
	int centery = m_Image.height() / 2;
	// which need to be shifted to account for panning inside that chunk
	centerx -= (m_X - centerchunkx * 16) * m_Zoom;
	centery -= (m_Z - centerchunkz * 16) * m_Zoom;
	// centerx,y now points to the top left corner of the center chunk
	// so now calculate our x,y in relation
	double chunksize = 16 * m_Zoom;
	centerx += (a_ChunkX - centerchunkx) * chunksize;
	centery += (a_ChunkZ - centerchunkz) * chunksize;

	uchar * bits = m_Image.bits();
	int imgstride = m_Image.bytesPerLine();

	int skipx = 0, skipy = 0;
	int blockwidth = chunksize, blockheight = chunksize;
	// now if we're off the screen we need to crop
	if (centerx < 0)
	{
		skipx = -centerx;
		centerx = 0;
	}
	if (centery < 0)
	{
		skipy = -centery;
		centery = 0;
	}
	// or the other side, we need to trim
	if (centerx + blockwidth > m_Image.width())
	{
		blockwidth = m_Image.width() - centerx;
	}
	if (centery + blockheight > m_Image.height())
	{
		blockheight = m_Image.height() - centery;
	}
	if ((blockwidth <= 0) || (skipx >= blockwidth))
	{
		return;
	}
	int imgoffset = centerx * 4 + centery * imgstride;

	// If the chunk is valid, use its data; otherwise use the empty placeholder:
	const short * src = m_EmptyChunkBiomes;
	if (region.get() != nullptr)
	{
		int relChunkX = a_ChunkX - regionX * 32;
		int relChunkZ = a_ChunkZ - regionZ * 32;
		Chunk & chunk = region->getRelChunk(relChunkX, relChunkZ);
		if (chunk.isValid())
		{
			src = chunk.getBiomes();
		}
	}

	// Scale-blit the image:
	for (int z = skipy; z < blockheight; z++, imgoffset += imgstride)
	{
		size_t srcoffset = static_cast<size_t>(std::floor((double)z / m_Zoom)) * 16;
		int imgxoffset = imgoffset;
		for (int x = skipx; x < blockwidth; x++)
		{
			short biome = src[srcoffset + static_cast<size_t>(std::floor((double)x / m_Zoom))];
			const uchar * color;
			if (biome < 0)
			{
				static const uchar emptyBiome1[] = { 0x44, 0x44, 0x44, 0xff };
				static const uchar emptyBiome2[] = { 0x88, 0x88, 0x88, 0xff };
				color = ((x & 8) ^ (z & 8)) ? emptyBiome1 : emptyBiome2;
			}
			else
			{
				if (biome * 4 >= ARRAYCOUNT(biomeToColor))
				{
					static const uchar errorImage[] = { 0xff, 0x00, 0x00, 0xff };
					color = errorImage;
				}
				else
				{
					color = biomeToColor + biome * 4;
				}
			}
			bits[imgxoffset]     = color[0];
			bits[imgxoffset + 1] = color[1];
			bits[imgxoffset + 2] = color[2];
			bits[imgxoffset + 3] = color[3];
			imgxoffset += 4;
		}  // for x
	}  // for z
}
void petabricks::CodeGenerator::mkCreateGpuSpatialMethodCallTask(
    const std::string& transname,
    const std::string& taskname, 
    const std::string& objname, 
    const std::string& methodname, 
    const SimpleRegion& region, 
    std::vector<RegionNodeGroup>& regionNodesGroups, 
    int nodeID, 
    int gpuCopyOut, 
    RegionList to, 
    bool divisible) {
  std::string taskclass
;
  int dim_int = region.totalDimensions();
  std::string lastdim = jalib::XToString(dim_int - 1);
  std::string max = region.maxCoord()[dim_int - 1]->toString();
  std::string min = region.minCoord()[dim_int - 1]->toString();

  if(!divisible) {
    taskclass = "petabricks::CreateGpuSpatialMethodCallTask<"+objname
      + ", " + jalib::XToString(region.totalDimensions())
      + ", &" + objname + "::" + methodname + TX_OPENCL_POSTFIX + "_createtasks"
      + ">";
    //beginIf(min+"<"+max);
    comment("MARKER 6");
    write("IndexT _tmp_begin[] = {" + region.getIterationLowerBounds() + "};");
    write("IndexT _tmp_end[] = {"   + region.getIterationUpperBounds() + "};");
    write("RegionNodeGroupMapPtr groups = new RegionNodeGroupMap();");
    for(std::vector<RegionNodeGroup>::iterator group = regionNodesGroups.begin(); group != regionNodesGroups.end(); ++group){
      write("{");
      incIndent();
      write("std::set<int> ids;");
      for(std::vector<int>::iterator id = group->nodeIDs().begin(); id != group->nodeIDs().end(); ++id){
	write("ids.insert("+jalib::XToString(*id)+");");
      }
      write("groups->insert(RegionNodeGroup(\""+group->matrixName()+"\",ids));");
      decIndent();
      write("}");
    }
    write(taskname+" = new "+taskclass+"(this,_tmp_begin, _tmp_end, "+jalib::XToString(nodeID)+", groups, "+jalib::XToString(gpuCopyOut)+");");
    //endIf();

    return;
  }

  std::string n_div = "cont_" + jalib::XToString(_contCounter++);
  write(taskname + " = new petabricks::MethodCallTask<"+_curClass+", &"+_curClass+"::"+n_div+">( this );");

  // Add divider function
  CodeGenerator helper = forkhelper();
  helper.beginFunc("DynamicTaskPtr", n_div);
  helper.write("DynamicTaskPtr _fini = new NullDynamicTask();");

  // Assign the gpu-cpu division point.
  helper.write("ElementT gpu_ratio = "+transname+"_gpuratio/8.0;");

  std::string div = "div";
  RegionPtr proxy = to.front();
  helper.write("IndexT totalRow = "+proxy->matrix()->name()+".size("+jalib::XToString(dim_int - 1)+");");
  helper.write("IndexT div = ceil(gpu_ratio * totalRow);");
  helper.beginIf("div > " + max);
  helper.write("div = "+max+";");
  helper.endIf();

  // GPU

  taskclass = "petabricks::CreateGpuSpatialMethodCallTask<"+objname
              + ", " + jalib::XToString(dim_int)
              + ", &" + objname + "::" + methodname + TX_OPENCL_POSTFIX + "_createtasks"
              + ">";
  helper.comment("MARKER 6");
  
  //helper.beginIf(min+" < div");
  helper.write("IndexT _gpu_begin[] = {" + region.getIterationLowerBounds() + "};");
  helper.write("IndexT _gpu_end[] = {" + region.getIterationMiddleEnd(div) + "};");
  helper.write("RegionNodeGroupMapPtr groups = new RegionNodeGroupMap();");

  for(std::vector<RegionNodeGroup>::iterator group = regionNodesGroups.begin(); group != regionNodesGroups.end(); ++group){
    helper.write("{");
    helper.incIndent();
    helper.write("std::set<int> ids;");
    for(std::vector<int>::iterator id = group->nodeIDs().begin(); id != group->nodeIDs().end(); ++id){
      helper.write("ids.insert("+jalib::XToString(*id)+");");
    }
    helper.write("groups->insert(RegionNodeGroup(\""+group->matrixName()+"\",ids));");
    helper.decIndent();
    helper.write("}");
  }

  helper.write("DynamicTaskPtr gpu_task = new "+taskclass+"(this,_gpu_begin, _gpu_end, "+jalib::XToString(nodeID)+", groups, "+jalib::XToString(gpuCopyOut)+");");
  helper.write("gpu_task->enqueue();");
  helper.write("_fini->dependsOn(gpu_task);");
  //helper.endIf();

  // CPU
  taskclass = "petabricks::SpatialMethodCallTask<CLASS"
              ", " + jalib::XToString(dim_int)
              + ", &CLASS::" + methodname + "_workstealing_wrap"
    //+ ", &CLASS::" + methodname + "_workstealing"
              + ">";
  helper.beginIf("div < " + max);
  helper.beginIf("div < " + min);
  helper.write("div = "+min+";");
  helper.endIf();
  helper.comment("MARKER 6");
  helper.write("IndexT _cpu_begin[] = {" + region.getIterationMiddleBegin(div) + "};");
  helper.write("IndexT _cpu_end[] = {"   + region.getIterationUpperBounds() + "};");
  helper.write("DynamicTaskPtr cpu_task = new "+taskclass+"(this,_cpu_begin, _cpu_end);");
  helper.write("cpu_task->enqueue();");
  helper.write("_fini->dependsOn(cpu_task);");
  helper.endIf();
  
  helper.write("return _fini;");
  helper.endFunc();
}