void write_image(const string& file, const SampleBuffer& buffer) { const float samples = static_cast<float>(buffer.samples()); FIBITMAP* dib = FreeImage_Allocate(buffer.width(), buffer.height(), 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); const unsigned int BYTESPP = FreeImage_GetLine(dib) / FreeImage_GetWidth(dib); for (unsigned int y = 0; y < FreeImage_GetHeight(dib); ++y) { BYTE* bits = FreeImage_GetScanLine(dib, y); for (unsigned int x = 0; x < FreeImage_GetWidth(dib); ++x) { vec3 c = gamma_correct(buffer.get(x, y) / samples) * 255.0f; bits[FI_RGBA_RED] = static_cast<BYTE>(c.r); bits[FI_RGBA_GREEN] = static_cast<BYTE>(c.g); bits[FI_RGBA_BLUE] = static_cast<BYTE>(c.b); bits[FI_RGBA_ALPHA] = 255; bits += BYTESPP; } } if (!FreeImage_Save(FIF_PNG, dib, file.c_str(), 0)) { string err = "Failed to save screenshot to file '"; err += file; err += '\''; throw err; } FreeImage_Unload(dib); }
void LfoControllerDialog::askUserDefWave() { SampleBuffer * sampleBuffer = dynamic_cast<LfoController*>(this->model())-> m_userDefSampleBuffer; QString fileName = sampleBuffer->openAndSetWaveformFile(); if( fileName.isEmpty() == false ) { // TODO: ToolTip::add( m_userWaveBtn, sampleBuffer->audioFile() ); } }
void SampleBuffer::append(const SampleBuffer& other) { assert(width() == other.width() && height() == other.height()); auto it = _buffer.begin(); auto io = other._buffer.cbegin(); while (it < _buffer.cend()) { *it += *io; ++it; ++io; } _samples += other.samples(); }
void SampleFrontEnd<sample_base_t>::Clear( ) { //temporary pointer SampleBuffer<sample_base_t>* pSampleBuff; for(std::map<std::string,std::pair<SampleSink*,SampleStreamInfo*>>::iterator mit = this->mSampleSinks.begin(); mit != this->mSampleSinks.end(); mit++) { pSampleBuff = dynamic_cast<SampleBuffer<sample_base_t>*>( mit->second.first ); if( pSampleBuff ) pSampleBuff->Flush(); } };
/// Write the summary to disk, using the derived ReadData() to get the data /// Here, the decoder ODTask associated with this file must fetch the samples with /// the ODDecodeTask::Decode() method. int ODDecodeBlockFile::WriteODDecodeBlockFile() { // To build the summary data, call ReadData (implemented by the // derived classes) to get the sample data SampleBuffer sampleData;// = NewSamples(mLen, floatSample); int ret; //use the decoder here. mDecoderMutex.Lock(); if(!mDecoder) { mDecoderMutex.Unlock(); return -1; } //sampleData and mFormat are set by the decoder. ret = mDecoder->Decode(sampleData, mFormat, mAliasStart, mLen, mAliasChannel); mDecoderMutex.Unlock(); if(ret < 0) { printf("ODDecodeBlockFile Decode failure\n"); return ret; //failure } //the summary is also calculated here. mFileNameMutex.Lock(); //TODO: we may need to write a version of WriteSimpleBlockFile that uses threadsafe FILE vs wxFile bool bSuccess = WriteSimpleBlockFile( sampleData.ptr(), mLen, mFormat, NULL);//summaryData); wxASSERT(bSuccess); // TODO: Handle failure here by alert to user and undo partial op. wxUnusedVar(bSuccess); mFileNameMutex.Unlock(); // delete [] (char *) summaryData; mDataAvailableMutex.Lock(); mDataAvailable=true; mDataAvailableMutex.Unlock(); return ret; }
void write_bitmap(char const * path, SampleBuffer const & buffer) { FILE * fd = fopen(path, "wb"); BitmapHeader header; BitmapInfo info = make_info(buffer.get_width(), buffer.get_height()); header.size() = sizeof(header) + sizeof(info) + buffer.get_size() * sizeof(uint32); header.offset() = sizeof(header) + sizeof(info); fwrite(&header, sizeof(header), 1, fd); fwrite(&info, sizeof(info), 1, fd); buffer.write_bitmap(fd); fclose(fd); }
void DSP::Filter::Gain::processSamples(SampleBuffer& samples) { for(int i = 0; i < samples.size(); ++i) { auto scaled = static_cast<int64_t>(samples[i]) * m_gain; samples[i] = saturate<int16_t>(scaled >> 16); } }
SampleBuffer *NativeFilm::GetFreeSampleBuffer() { // Look for a free buffer if (freeSampleBuffers.size() > 0) { SampleBuffer *sb = freeSampleBuffers.front(); freeSampleBuffers.pop_front(); sb->Reset(); return sb; } else { // Need to allocate a new buffer SampleBuffer *sb = new SampleBuffer(SampleBufferSize); sampleBuffers.push_back(sb); return sb; } }
QString graphModel::setWaveToUser() { SampleBuffer * sampleBuffer = new SampleBuffer; QString fileName = sampleBuffer->openAndSetWaveformFile(); if( fileName.isEmpty() == false ) { for( int i = 0; i < length(); i++ ) { m_samples[i] = sampleBuffer->userWaveSample( i / static_cast<float>( length() ) ); } } sharedObject::unref( sampleBuffer ); emit samplesChanged( 0, length() - 1 ); return fileName; };
void SingularSampleBuffer::swapBuffers(SampleBuffer& secondaryBuffer) { DEBUG_ASSERT_CLASS_INVARIANT_SingularSampleBuffer; DEBUG_ASSERT(m_primaryBuffer.size() == secondaryBuffer.size()); // SampleUtil::copy() requires that the source and destination // memory regions are disjunct. Double-buffering is necessary // to satisfy this precondition. SampleUtil::copy( secondaryBuffer.data(), m_primaryBuffer.data(m_headOffset), getSize()); m_primaryBuffer.swap(secondaryBuffer); // shift offsets m_tailOffset -= m_headOffset; m_headOffset = 0; DEBUG_ASSERT_CLASS_INVARIANT_SingularSampleBuffer; }
void SoundEngine::MusicHook(void* userdata, Uint8* stream, int len) { bool* musicFinishedPtr = reinterpret_cast<bool*>(userdata); if (!*musicFinishedPtr) { SampleBuffer buffer; Uint32 ret = musicDecoder.Decode(buffer, len); if (ret == SOUND_DECODE_COMPLETED) { musicDecoder.Close(); *musicFinishedPtr = true; } else if (ret == SOUND_DECODE_ERROR) { logger->error("Sound: Error during music decoding, stopping playback of current track.\n"); *musicFinishedPtr = true; return; } memcpy(stream, &buffer[0], buffer.size()); } }
//--Decoder stuff: ///Decodes the samples for this blockfile from the real file into a float buffer. ///This is file specific, so subclasses must implement this only. ///the buffer was defined like ///samplePtr sampleData = NewSamples(mLen, floatSample); ///this->ReadData(sampleData, floatSample, 0, mLen); ///This class should call ReadHeader() first, so it knows the length, and can prepare ///the file object if it needs to. int ODFlacDecoder::Decode(SampleBuffer & data, sampleFormat & format, sampleCount start, size_t len, unsigned int channel) { //we need to lock this so the target stays fixed over the seek/write callback. mFlacFileLock.Lock(); bool usingCache=mLastDecodeStartSample==start; if(usingCache) { //we've just decoded this, so lets use a cache. (often so for } mDecodeBufferWritePosition=0; mDecodeBufferLen = len; data.Allocate(len, mFormat); mDecodeBuffer = data.ptr(); format = mFormat; mTargetChannel=channel; // Third party library has its own type alias, check it static_assert(sizeof(sampleCount::type) <= sizeof(FLAC__int64), "Type FLAC__int64 is too narrow to hold a sampleCount"); if(!mFile->seek_absolute(static_cast<FLAC__int64>( start.as_long_long() ))) { mFlacFileLock.Unlock(); return -1; } while(mDecodeBufferWritePosition<mDecodeBufferLen) mFile->process_single(); mFlacFileLock.Unlock(); if(!usingCache) { mLastDecodeStartSample=start; } //insert into blockfile and //calculate summary happen in ODDecodeBlockFile::WriteODDecodeBlockFile, where this method is also called. return 1; }
SampleBuffer *NativePixelDevice::GetFreeSampleBuffer() { boost::mutex::scoped_lock lock(splatMutex); // Look for a free buffer if (freeSampleBuffers.size() > 0) { SampleBuffer *sb = freeSampleBuffers.front(); freeSampleBuffers.pop_front(); sb->Reset(); return sb; } else { // Need to allocate a new buffer SampleBuffer *sb = new SampleBuffer(SampleBufferSize); sampleBuffers.push_back(sb); return sb; } }
void UniformSampleGenerator2DCL::generateNextSamples(SampleBuffer& positionSamplesOut, const VECTOR_CLASS<cl::Event>* waitForEvents /*= nullptr*/, cl::Event* event /*= nullptr*/) { if (kernel_ == NULL) { return throw Exception("Invalid kernel: Kernel not found or failed to compile"); } size2_t nSamples{static_cast<size_t>(std::sqrt(static_cast<double>(positionSamplesOut.getSize())))}; if (getUseGLSharing()) { SyncCLGL glSync; BufferCLGL* samples = positionSamplesOut.getEditableRepresentation<BufferCLGL>(); // Acquire shared representations before using them in OpenGL // The SyncCLGL object will take care of synchronization between OpenGL and OpenCL glSync.addToAquireGLObjectList(samples); glSync.aquireAllObjects(); generateSamples(nSamples, positionSamplesOut.getSize(), samples, waitForEvents, event); } else { BufferCL* samples = positionSamplesOut.getEditableRepresentation<BufferCL>(); generateSamples(nSamples, positionSamplesOut.getSize(), samples, waitForEvents, event); } }
/// Write the summary to disk, using the derived ReadData() to get the data /// Here, the decoder ODTask associated with this file must fetch the samples with /// the ODDecodeTask::Decode() method. int ODDecodeBlockFile::WriteODDecodeBlockFile() { // To build the summary data, call ReadData (implemented by the // derived classes) to get the sample data SampleBuffer sampleData;// = NewSamples(mLen, floatSample); int ret; { //use the decoder here. ODLocker locker{ &mDecoderMutex }; if(!mDecoder) return -1; //sampleData and mFormat are set by the decoder. ret = mDecoder->Decode(sampleData, mFormat, mAliasStart, mLen, mAliasChannel); if(ret < 0) { wxPrintf("ODDecodeBlockFile Decode failure\n"); return ret; //failure } } { //the summary is also calculated here. ODLocker locker{ &mFileNameMutex }; //TODO: we may need to write a version of WriteSimpleBlockFile that uses threadsafe FILE vs wxFile bool bSuccess = WriteSimpleBlockFile( sampleData.ptr(), mLen, mFormat, NULL); if ( !bSuccess ) return -1; } wxAtomicInc( mDataAvailable ); return ret; }
void SampleBuffer::normalizeSampleRate( const sample_rate_t _src_sr, bool _keep_settings ) { // do samplerate-conversion to our default-samplerate if( _src_sr != engine::mixer()->baseSampleRate() ) { SampleBuffer * resampled = resample( this, _src_sr, engine::mixer()->baseSampleRate() ); MM_FREE( m_data ); m_frames = resampled->frames(); m_data = MM_ALLOC( sampleFrame, m_frames ); memcpy( m_data, resampled->data(), m_frames * sizeof( sampleFrame ) ); delete resampled; } if( _keep_settings == false ) { // update frame-variables m_loopStartFrame = m_startFrame = 0; m_loopEndFrame = m_endFrame = m_frames; } }
void processBlock(){ buffer.split(getProgramVector()->audio_input, getProgramVector()->audio_blocksize); patches.process(buffer); buffer.comb(getProgramVector()->audio_output); }
Uint32 SoundFile::Decode(SampleBuffer& buffer, Uint32 length) { if (!initconv || !fileOpened) { return SOUND_DECODE_ERROR; } assert(buffer.empty()); Uint32 max_size = length == 0 ? uncomp_size * conv->len_mult : length; buffer.resize(max_size); Uint16 comp_sample_size, uncomp_sample_size; Uint32 ID; //if (offset < 12) // offset = 12; //file->seekSet(offset); Uint32 written = 0; while ((file->tell()+8) < file->fileSize()) { // Each sample has a header file->readWord(&comp_sample_size, 1); file->readWord(&uncomp_sample_size, 1); file->readDWord(&ID, 1); if (comp_sample_size > (SOUND_MAX_CHUNK_SIZE)) { logger->warning("Size data for current sample too large\n"); return SOUND_DECODE_ERROR; } // abort if id was wrong */ if (ID != 0xDEAF) { logger->warning("Sample had wrong ID: %x\n", ID); return SOUND_DECODE_ERROR; } if (written + uncomp_sample_size*conv->len_mult > max_size) { file->seekCur(-8); // rewind stream back to headers buffer.resize(written); // Truncate buffer. return SOUND_DECODE_STREAMING; } // compressed data follows header file->readByte(chunk, comp_sample_size); if (type == 1) { SoundUtils::WSADPCM_Decode(tmpbuff, chunk, comp_sample_size, uncomp_sample_size); } else { SoundUtils::IMADecode(tmpbuff, chunk, comp_sample_size, imaSample, imaIndex); } conv->buf = tmpbuff; conv->len = uncomp_sample_size; if (SDL_ConvertAudio(conv) < 0) { logger->warning("Could not run conversion filter: %s\n", SDL_GetError()); return SOUND_DECODE_ERROR; } memcpy(&buffer[written], tmpbuff, uncomp_sample_size*conv->len_mult); //offset += 8 + comp_sample_size; written += uncomp_sample_size*conv->len_mult; } // Truncate if final sample was too small. if (written < max_size) buffer.resize(written); return SOUND_DECODE_COMPLETED; }
int ODFFmpegDecoder::Decode(SampleBuffer & data, sampleFormat & format, sampleCount start, sampleCount len, unsigned int channel) { format = mScs[mStreamIndex]->m_osamplefmt; data.Allocate(len, format); samplePtr bufStart = data.ptr(); streamContext* sc = NULL; // printf("start %llu len %llu\n", start, len); //TODO update this to work with seek - this only works linearly now. if(mCurrentPos > start && mCurrentPos <= start+len + kDecodeSampleAllowance) { //this next call takes data, start and len as reference variables and updates them to reflect the NEW area that is needed. FillDataFromCache(bufStart, format, start,len,channel); } bool seeking = false; //look at the decoding timestamp and see if the next sample that will be decoded is not the next sample we need. if(len && (mCurrentPos > start + len || mCurrentPos + kDecodeSampleAllowance < start ) && SeekingAllowed()) { sc = mScs[mStreamIndex]; AVStream* st = sc->m_stream; int stindex = -1; uint64_t targetts; //printf("attempting seek to %llu\n", start); //we have to find the index for this stream. for (unsigned int i = 0; i < mFormatContext->nb_streams; i++) { if (mFormatContext->streams[i] == sc->m_stream ) stindex =i; } if(stindex >=0) { int numAttempts = 0; //reset mCurrentPos to a bogus value mCurrentPos = start+len +1; while(numAttempts++ < kMaxSeekRewindAttempts && mCurrentPos > start) { //we want to move slightly before the start of the block file, but not too far ahead targetts = (start-kDecodeSampleAllowance*numAttempts/kMaxSeekRewindAttempts) * ((double)st->time_base.den/(st->time_base.num * st->codec->sample_rate )); if(targetts<0) targetts=0; //printf("attempting seek to %llu, attempts %d\n", targetts, numAttempts); if(av_seek_frame(mFormatContext,stindex,targetts,0) >= 0){ //find out the dts we've seekd to. sampleCount actualDecodeStart = 0.5 + st->codec->sample_rate * st->cur_dts * ((double)st->time_base.num/st->time_base.den); //this is mostly safe because den is usually 1 or low number but check for high values. mCurrentPos = actualDecodeStart; seeking = true; //if the seek was past our desired position, rewind a bit. //printf("seek ok to %llu samps, float: %f\n",actualDecodeStart,actualDecodeStartDouble); } else { printf("seek failed"); break; } } if(mCurrentPos>start){ mSeekingAllowedStatus = (bool)ODFFMPEG_SEEKING_TEST_FAILED; // url_fseek(mFormatContext->pb,sc->m_pkt.pos,SEEK_SET); printf("seek fail, reverting to previous pos\n"); return -1; } } } bool firstpass = true; //we decode up to the end of the blockfile while (len>0 && (mCurrentPos < start+len) && (sc = ReadNextFrame()) != NULL) { // ReadNextFrame returns 1 if stream is not to be imported if (sc != (streamContext*)1) { //find out the dts we've seekd to. can't use the stream->cur_dts because it is faulty. also note that until we do the first seek, pkt.dts can be false and will change for the same samples after the initial seek. sampleCount actualDecodeStart = mCurrentPos; // we need adjacent samples, so don't use dts most of the time which will leave gaps between frames // for some formats // The only other case for inserting silence is for initial offset and ImportFFmpeg.cpp does this for us if (seeking) { actualDecodeStart = 0.52 + (sc->m_stream->codec->sample_rate * sc->m_pkt.dts * ((double)sc->m_stream->time_base.num / sc->m_stream->time_base.den)); //this is mostly safe because den is usually 1 or low number but check for high values. //hack to get rounding to work to neareset frame size since dts isn't exact if (sc->m_stream->codec->frame_size) { actualDecodeStart = ((actualDecodeStart + sc->m_stream->codec->frame_size/2) / sc->m_stream->codec->frame_size) * sc->m_stream->codec->frame_size; } // reset for the next one seeking = false; } if(actualDecodeStart != mCurrentPos) printf("ts not matching - now:%llu , last:%llu, lastlen:%llu, start %llu, len %llu\n",actualDecodeStart, mCurrentPos, mCurrentLen, start, len); //if we've skipped over some samples, fill the gap with silence. This could happen often in the beginning of the file. if(actualDecodeStart>start && firstpass) { // find the number of samples for the leading silence int amt = actualDecodeStart - start; FFMpegDecodeCache* cache = new FFMpegDecodeCache; //printf("skipping/zeroing %i samples. - now:%llu (%f), last:%llu, lastlen:%llu, start %llu, len %llu\n",amt,actualDecodeStart, actualDecodeStartdouble, mCurrentPos, mCurrentLen, start, len); //put it in the cache so the other channels can use it. cache->numChannels = sc->m_stream->codec->channels; cache->len = amt; cache->start=start; // 8 bit and 16 bit audio output from ffmpeg means // 16 bit int out. // 32 bit int, float, double mean float out. if (format == int16Sample) cache->samplefmt = SAMPLE_FMT_S16; else cache->samplefmt = SAMPLE_FMT_FLT; cache->samplePtr = (uint8_t*) malloc(amt * cache->numChannels * SAMPLE_SIZE(format)); memset(cache->samplePtr, 0, amt * cache->numChannels * SAMPLE_SIZE(format)); InsertCache(cache); } firstpass=false; mCurrentPos = actualDecodeStart; //decode the entire packet (unused bits get saved in cache, so as long as cache size limit is bigger than the //largest packet size, we're ok. while (sc->m_pktRemainingSiz > 0) //Fill the cache with decoded samples if (DecodeFrame(sc,false) < 0) break; // Cleanup after frame decoding if (sc->m_pktValid) { av_free_packet(&sc->m_pkt); sc->m_pktValid = 0; } } } // Flush the decoders if we're done. if((!sc || sc == (streamContext*) 1)&& len>0) { for (int i = 0; i < mNumStreams; i++) { if (DecodeFrame(mScs[i], true) == 0) { if (mScs[i]->m_pktValid) { av_free_packet(&mScs[i]->m_pkt); mScs[i]->m_pktValid = 0; } } } } //this next call takes data, start and len as reference variables and updates them to reflect the NEW area that is needed. FillDataFromCache(bufStart, format, start, len, channel); // CHECK: not sure if we need this. In any case it has to be updated for the NEW float case (not just int16) //if for some reason we couldn't get the samples, fill them with silence /* int16_t* outBuf = (int16_t*) bufStart; for(int i=0;i<len;i++) outBuf[i]=0; */ return 1; }
int main() { sf::RenderWindow window(sf::VideoMode(900, 600), "Path Tracing 2D"); window.setVerticalSyncEnabled(true); glewInit(); glMatrixMode(GL_PROJECTION); Matrix4x4f::OrthoMatrix(0.0f, 900.0f, 0.0f, 600.0f, -1.0f, 1.0f).GL_Load(); SampleBuffer buffer; const float sampleScalar = 1.0f; const int downsampledWidth = window.getSize().x * sampleScalar; const int downsampledHeight = window.getSize().y * sampleScalar; if(!buffer.Create(downsampledWidth, downsampledHeight, "NONE NONE tracerShader.frag")) abort(); buffer.Clear(AABB2D(Vec2f(-downsampledWidth, -downsampledHeight), Vec2f(downsampledWidth, downsampledHeight))); Light light; light.m_position = Vec3f(0.0f, 0.0f, 32.0f); light.m_color = Vec3f(10.0f, 10.0f, 10.0f); buffer.m_scene.m_lights.push_back(light); Polygon2D basePoly; basePoly.m_points.resize(4); basePoly.m_points[0] = Vec2f(-50.0f, -50.0f) * sampleScalar; basePoly.m_points[1] = Vec2f(50.0f, -50.0f) * sampleScalar; basePoly.m_points[2] = Vec2f(50.0f, 50.0f) * sampleScalar; basePoly.m_points[3] = Vec2f(-50.0f, 50.0f) * sampleScalar; buffer.Add(basePoly); Polygon2D basePoly2; basePoly2.m_points.resize(4); basePoly2.m_points[0] = Vec2f(-50.0f, 100.0f) * sampleScalar; basePoly2.m_points[1] = Vec2f(50.0f, 100.0f) * sampleScalar; basePoly2.m_points[2] = Vec2f(50.0f, 200.0f) * sampleScalar; basePoly2.m_points[3] = Vec2f(-50.0f, 200.0f) * sampleScalar; buffer.Add(basePoly2); buffer.Compile(); buffer.Refresh(); bool close = false; while(!close) { sf::Event event; while(window.pollEvent(event)) { if(event.type == sf::Event::Closed) close = true; if(event.type == sf::Event::MouseMoved) { buffer.Refresh(); buffer.m_scene.m_lights.back().m_position = Vec3f((event.mouseMove.x - 450) * sampleScalar, (300 - event.mouseMove.y) * sampleScalar, 32.0f); } } if(sf::Keyboard::isKeyPressed(sf::Keyboard::Escape)) close = true; for(size_t i = 0; i < 1; i++) buffer.Accumulate(Vec2f(0.0f, 0.0f), Vec2f(downsampledWidth, downsampledHeight), 0.0f); glFlush(); glViewport(0, 0, window.getSize().x, window.getSize().y); buffer.RenderBuffer(Vec2f(0.0f, 0.0f), Vec2f(900.0f, 600.0f), 0.0f); window.display(); } return 0; }