/[svn]/libgig/trunk/src/gig.cpp
ViewVC logotype

Diff of /libgig/trunk/src/gig.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 21 by schoenebeck, Thu Dec 25 01:09:08 2003 UTC revision 27 by schoenebeck, Thu Jan 1 23:46:41 2004 UTC
# Line 73  namespace gig { Line 73  namespace gig {
73          }          }
74          FrameOffset = 0; // just for streaming compressed samples          FrameOffset = 0; // just for streaming compressed samples
75    
76          LoopStart /= FrameSize; // convert to sample points          LoopSize = LoopEnd - LoopStart;
         LoopEnd   /= FrameSize; // convert to sample points  
         LoopSize   = LoopEnd - LoopStart;  
77      }      }
78    
79      /// Scans compressed samples for mandatory informations (e.g. actual number of total sample points).      /// Scans compressed samples for mandatory informations (e.g. actual number of total sample points).
# Line 315  namespace gig { Line 313  namespace gig {
313      }      }
314    
315      /**      /**
316         * Reads \a SampleCount number of sample points from the position stored
317         * in \a pPlaybackState into the buffer pointed by \a pBuffer and moves
318         * the position within the sample respectively, this method honors the
319         * looping informations of the sample (if any). The sample wave stream
320         * will be decompressed on the fly if using a compressed sample. Use this
321         * method if you don't want to load the sample into RAM, thus for disk
322         * streaming. All this methods needs to know to proceed with streaming
323         * for the next time you call this method is stored in \a pPlaybackState.
324         * You have to allocate and initialize the playback_state_t structure by
325         * yourself before you use it to stream a sample:
326         *
327         * <i>
328         * gig::playback_state_t playbackstate;                           <br>
329         * playbackstate.position         = 0;                            <br>
330         * playbackstate.reverse          = false;                        <br>
331         * playbackstate.loop_cycles_left = pSample->LoopPlayCount;       <br>
332         * </i>
333         *
334         * You don't have to take care of things like if there is actually a loop
335         * defined or if the current read position is located within a loop area.
336         * The method already handles such cases by itself.
337         *
338         * @param pBuffer          destination buffer
339         * @param SampleCount      number of sample points to read
340         * @param pPlaybackState   will be used to store and reload the playback
341         *                         state for the next ReadAndLoop() call
342         * @returns                number of successfully read sample points
343         */
344        unsigned long Sample::ReadAndLoop(void* pBuffer, unsigned long SampleCount, playback_state_t* pPlaybackState) {
345            unsigned long samplestoread = SampleCount, totalreadsamples = 0, readsamples, samplestoloopend;
346            uint8_t* pDst = (uint8_t*) pBuffer;
347    
348            SetPos(pPlaybackState->position); // recover position from the last time
349    
350            if (this->Loops && GetPos() <= this->LoopEnd) { // honor looping if there are loop points defined
351    
352                switch (this->LoopType) {
353    
354                    case loop_type_bidirectional: { //TODO: not tested yet!
355                        do {
356                            // if not endless loop check if max. number of loop cycles have been passed
357                            if (this->LoopPlayCount && !pPlaybackState->loop_cycles_left) break;
358    
359                            if (!pPlaybackState->reverse) { // forward playback
360                                do {
361                                    samplestoloopend  = this->LoopEnd - GetPos();
362                                    readsamples       = Read(&pDst[totalreadsamples * this->FrameSize], Min(samplestoread, samplestoloopend));
363                                    samplestoread    -= readsamples;
364                                    totalreadsamples += readsamples;
365                                    if (readsamples == samplestoloopend) {
366                                        pPlaybackState->reverse = true;
367                                        break;
368                                    }
369                                } while (samplestoread && readsamples);
370                            }
371                            else { // backward playback
372    
373                                // as we can only read forward from disk, we have to
374                                // determine the end position within the loop first,
375                                // read forward from that 'end' and finally after
376                                // reading, swap all sample frames so it reflects
377                                // backward playback
378    
379                                unsigned long swapareastart       = totalreadsamples;
380                                unsigned long loopoffset          = GetPos() - this->LoopStart;
381                                unsigned long samplestoreadinloop = Min(samplestoread, loopoffset);
382                                unsigned long reverseplaybackend  = GetPos() - samplestoreadinloop;
383    
384                                SetPos(reverseplaybackend);
385    
386                                // read samples for backward playback
387                                do {
388                                    readsamples          = Read(&pDst[totalreadsamples * this->FrameSize], samplestoreadinloop);
389                                    samplestoreadinloop -= readsamples;
390                                    samplestoread       -= readsamples;
391                                    totalreadsamples    += readsamples;
392                                } while (samplestoreadinloop && readsamples);
393    
394                                SetPos(reverseplaybackend); // pretend we really read backwards
395    
396                                if (reverseplaybackend == this->LoopStart) {
397                                    pPlaybackState->loop_cycles_left--;
398                                    pPlaybackState->reverse = false;
399                                }
400    
401                                // reverse the sample frames for backward playback
402                                SwapMemoryArea(&pDst[swapareastart * this->FrameSize], (totalreadsamples - swapareastart) * this->FrameSize, this->FrameSize);
403                            }
404                        } while (samplestoread && readsamples);
405                        break;
406                    }
407    
408                    case loop_type_backward: { // TODO: not tested yet!
409                        // forward playback (not entered the loop yet)
410                        if (!pPlaybackState->reverse) do {
411                            samplestoloopend  = this->LoopEnd - GetPos();
412                            readsamples       = Read(&pDst[totalreadsamples * this->FrameSize], Min(samplestoread, samplestoloopend));
413                            samplestoread    -= readsamples;
414                            totalreadsamples += readsamples;
415                            if (readsamples == samplestoloopend) {
416                                pPlaybackState->reverse = true;
417                                break;
418                            }
419                        } while (samplestoread && readsamples);
420    
421                        if (!samplestoread) break;
422    
423                        // as we can only read forward from disk, we have to
424                        // determine the end position within the loop first,
425                        // read forward from that 'end' and finally after
426                        // reading, swap all sample frames so it reflects
427                        // backward playback
428    
429                        unsigned long swapareastart       = totalreadsamples;
430                        unsigned long loopoffset          = GetPos() - this->LoopStart;
431                        unsigned long samplestoreadinloop = (this->LoopPlayCount) ? Min(samplestoread, pPlaybackState->loop_cycles_left * LoopSize - loopoffset)
432                                                                                  : samplestoread;
433                        unsigned long reverseplaybackend  = this->LoopStart + Abs((loopoffset - samplestoreadinloop) % this->LoopSize);
434    
435                        SetPos(reverseplaybackend);
436    
437                        // read samples for backward playback
438                        do {
439                            // if not endless loop check if max. number of loop cycles have been passed
440                            if (this->LoopPlayCount && !pPlaybackState->loop_cycles_left) break;
441                            samplestoloopend     = this->LoopEnd - GetPos();
442                            readsamples          = Read(&pDst[totalreadsamples * this->FrameSize], Min(samplestoreadinloop, samplestoloopend));
443                            samplestoreadinloop -= readsamples;
444                            samplestoread       -= readsamples;
445                            totalreadsamples    += readsamples;
446                            if (readsamples == samplestoloopend) {
447                                pPlaybackState->loop_cycles_left--;
448                                SetPos(this->LoopStart);
449                            }
450                        } while (samplestoreadinloop && readsamples);
451    
452                        SetPos(reverseplaybackend); // pretend we really read backwards
453    
454                        // reverse the sample frames for backward playback
455                        SwapMemoryArea(&pDst[swapareastart * this->FrameSize], (totalreadsamples - swapareastart) * this->FrameSize, this->FrameSize);
456                        break;
457                    }
458    
459                    default: case loop_type_normal: {
460                        do {
461                            // if not endless loop check if max. number of loop cycles have been passed
462                            if (this->LoopPlayCount && !pPlaybackState->loop_cycles_left) break;
463                            samplestoloopend  = this->LoopEnd - GetPos();
464                            readsamples       = Read(&pDst[totalreadsamples * this->FrameSize], Min(samplestoread, samplestoloopend));
465                            samplestoread    -= readsamples;
466                            totalreadsamples += readsamples;
467                            if (readsamples == samplestoloopend) {
468                                pPlaybackState->loop_cycles_left--;
469                                SetPos(this->LoopStart);
470                            }
471                        } while (samplestoread && readsamples);
472                        break;
473                    }
474                }
475            }
476    
477            // read on without looping
478            if (samplestoread) do {
479                readsamples = Read(&pDst[totalreadsamples * this->FrameSize], samplestoread);
480                samplestoread    -= readsamples;
481                totalreadsamples += readsamples;
482            } while (readsamples && samplestoread);
483    
484            // store current position
485            pPlaybackState->position = GetPos();
486    
487            return totalreadsamples;
488        }
489    
490        /**
491       * Reads \a SampleCount number of sample points from the current       * Reads \a SampleCount number of sample points from the current
492       * position into the buffer pointed by \a pBuffer and increments the       * position into the buffer pointed by \a pBuffer and increments the
493       * position within the sample. The sample wave stream will be       * position within the sample. The sample wave stream will be

Legend:
Removed from v.21  
changed lines
  Added in v.27

  ViewVC Help
Powered by ViewVC