19 May '13 - 18:02 *
Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
 
   Home   Help Search Login Register  
Pages: [1]
  Reply  |  Print  
Author Topic: Playing Mp3's backwards  (Read 3602 times)
Sl@jaR
Posts: 81


« on: 23 Apr '02 - 22:38 »
Reply with quoteQuote

Huh Right now i am trying to play a mp3 backwards...
I had an idea to buffer the mp3 first, but that takes too much time Sad Did anybody tryed this before?
Maybe i ll decode Mp3 by myself   Cry but i don't want to;)
Hopefully there is a better or easier solution.

Thanx Matthias
Logged
Sl@jaR
Posts: 81


« Reply #1 on: 23 Apr '02 - 23:44 »
Reply with quoteQuote

After i went through all these old posts i found :

http://www.un4seen.com/music/YaBB.cgi?board=bass&action=display&num=991003021

That's the perfect solution Wink It's a mini buffer solution  :evil:
Ian you are the GOD!!!  Grin


PS.: Ian, the search option in this board is not very good Sad
Logged
Ian @ un4seen
Administrator
Posts: 15244


« Reply #2 on: 24 Apr '02 - 12:06 »
Reply with quoteQuote

Ah, memories... I was so young then Grin

The code in that thread was written pre-"decoding channels", so it can actually be improved quite a bit...
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include "bass.h"

void Error(char *text)
{
     printf("Error(%d): %s\n",BASS_ErrorGetCode(),text);
     BASS_Free();
     ExitProcess(0);
}

typedef struct {
     HSTREAM str,rstr;
     int flags,dpos,buflen,bufp;
     char *buf;
} REVERSESTUFF;

/* play stream in reverse */
DWORD CALLBACK rev_stream(HSTREAM handle, DWORD *buffer, DWORD length, REVERSESTUFF *r)
{
     int a,c,l=length;
     while (l) {
           if (!r->bufp) { /* decode the next block */
                 if (r->dpos<=0) break; // all done
                 r->dpos-=r->buflen; // move to next block position
                 if (r->dpos<0) { // it's the last block
                       BASS_ChannelSetPosition(r->str,0);
                       r->bufp=BASS_ChannelGetData(r->str,r->buf,r->buflen+r->dpos);
                 } else {
                       BASS_ChannelSetPosition(r->str,r->dpos);
                       r->bufp=BASS_ChannelGetData(r->str,r->buf,r->buflen);
                 }
                 if (r->bufp<=0) break; // error
           }
           /* reverse the decoded data */
           c=min(l,r->bufp);
           if (r->flags&BASS_SAMPLE_MONO) {
                 short *b=buffer;
                 for (a=0;a<c/2;a++) {
                       *b=*(short*)(r->buf+r->bufp-2);
                       b++;
                       r->bufp-=2;
                 }
           } else {
                 for (a=0;a<c/4;a++) {
                       *buffer=*(DWORD*)(r->buf+r->bufp-4);
                       buffer++;
                       r->bufp-=4;
                 }
           }
           l-=c;
     }
     return length-l;
}

void main(int argc, char **argv)
{
     REVERSESTUFF r;
     int freq;

     if (argc!=2) {
           printf("\tusage: reverse <file>\n");
           return;
     }

     /* setup output - default device, 44100hz, stereo, 16 bits */
     if (!BASS_Init(-1,44100,BASS_DEVICE_NOSYNC,0))
           Error("Can't initialize device");

     /* try streaming the file (with pin-point seeking enabled) */
     if (!(r.str=BASS_StreamCreateFile(FALSE,argv[1],0,0,BASS_STREAM_DECODE|BASS_MP3_SETPOS)))
           Error("Can't play the file");

     /* get stream format and create new stream to play in reverse */
     r.flags=BASS_ChannelGetFlags(r.str)&~BASS_STREAM_DECODE;
     BASS_ChannelGetAttributes(r.str,&freq,0,0);
     r.rstr=BASS_StreamCreate(freq,r.flags,(STREAMPROC*)&rev_stream,&r);

     /* decode in 2 second blocks...
           larger blocks = less seeking overhead but larger spikes */
     r.buflen=BASS_ChannelSeconds2Bytes(r.str,2.0);
     r.buf=malloc(r.buflen);

     BASS_Start();

     /* set decode position to the start (ie. end) */
     r.dpos=BASS_StreamGetLength(r.str);
     r.bufp=0;

     BASS_StreamPlay(r.rstr,FALSE,0); // start it

     while (!_kbhit() && BASS_ChannelIsActive(r.rstr)) {
           /* display some stuff and wait a bit */
           printf("pos %09d - cpu %.1f%%  \r",
                 BASS_ChannelGetPosition(r.rstr),BASS_GetCPU());
           Sleep(50);
     }

     BASS_Free();
     free(r.buf);
}

Simpler, smaller, more efficient, more robust... better Grin

By the way, what don't you like about the search option?
Logged
paddy
Posts: 142


« Reply #3 on: 24 Apr '02 - 12:25 »
Reply with quoteQuote

Smiley Where art thou Jobnik!!  Smiley

Jobnik,

Can bass_pitch.dll be updated to include this?

Logged
(: JOBnik! :)
Posts: 984


« Reply #4 on: 26 Apr '02 - 12:31 »
Reply with quoteQuote

Grin Grin Grin Grin Grin

Hi,

Maybe it could be done   Tongue

Have fun!

Cool JOBnik! Cool
Logged
paddy
Posts: 142


« Reply #5 on: 6 May '02 - 09:00 »
Reply with quoteQuote

Jobnik,
Any luck on this?  Smiley
Logged
(: JOBnik! :)
Posts: 984


« Reply #6 on: 6 May '02 - 12:39 »
Reply with quoteQuote

Hi  Grin

I'm writing a new .DLL, I'm including there:

1. PITCH      (done!)
2. REVERSE  (done!)
3. DSP functions like:
    FLANGER, ECHO, VOLUME, ROTATE and SWAP
    CHANNELS   (almost done!)

+ functions to change FLANGER delay & wetdry, ECHO delay, VOLUME... Smiley

for now Smiley

Have fun!

Cool JOBnik! Cool
Logged
paddy
Posts: 142


« Reply #7 on: 6 May '02 - 12:47 »
Reply with quoteQuote

Shocked WOW! Shocked

How about EQ and Compression?   Cheesy
Logged
(: JOBnik! :)
Posts: 984


« Reply #8 on: 6 May '02 - 12:56 »
Reply with quoteQuote

Hi  Grin

I'll see what I can do Smiley

Have fun!

Cool JOBnik! Cool
Logged
Largie
Posts: 110


« Reply #9 on: 20 Jul '02 - 07:59 »
Reply with quoteQuote

Hi Ian..

I tried to use this code into my library and it does play the stream backwards, but there are something wrong...

(I guess the callback version is written for a early version of bass, but I guess that is not the problem)

It looks like to me, that when it is finished playing the first "block" of 2 secs, it go backwards and collect 0,5 secs of the last 2 secs and plays it again.... If I increase the secs to eg 5 secs, it is still failing on 0,5 secs on each block..

Now I found the error:


   /* try streaming the file (with pin-point seeking enabled) */
    if (!(r.str=BASS_StreamCreateFile(FALSE,argv[1],0,0,BASS_STREAM_DECODE|BASS_MP3_SETPOS)))
          Error("Can't play the file");


In BASS docs the params for StreamCreateFile does not include the BASS_MP3_SETPOS so I removed the flag... Now the sound is really choppy! Smiley Now the sound "repeated" itself cause of this code:


     float length=BASS_SetBufferLength[InstNr](0)-0.001; // get update period
     BASS_INFO info={sizeof(info)};
     BASS_GetInfo[InstNr](&info); // retrieve latency
     length+=info.latency/1000.0; // add the latency
     BASS_SetBufferLength[InstNr](length); // set the length


That is used to avoid "bloops" Wink So Ian, is the SETPOS param just forgotten in the docs?! Wink
« Last Edit: 20 Jul '02 - 09:05 by Largie » Logged
Ian @ un4seen
Administrator
Posts: 15244


« Reply #10 on: 20 Jul '02 - 11:07 »
Reply with quoteQuote

hmm... the BASS_MP3_SETPOS flag is still there in the BASS_StreamCreateFile docs, right between BASS_MP3_HALFRATE and BASS_STREAM_AUTOFREE Smiley

The BASS_MP3_SETPOS flag is required if you want to play an MP3 file in reverse (it's got to seek to exact byte positions). You shouldn't need to adjust the buffer length though.
Logged
Largie
Posts: 110


« Reply #11 on: 20 Jul '02 - 11:19 »
Reply with quoteQuote

Quote

hmm... the BASS_MP3_SETPOS flag is still there in the BASS_StreamCreateFile docs, right between BASS_MP3_HALFRATE and BASS_STREAM_AUTOFREE Smiley


Hanger over!  Cool

I see it now... I thought of the sync flag... Smiley Hehe.... Well... It is OK now... I have made a routine that does this:

playing forward
-> When user press reverse
Pause forward
GetForward pos
SetPos in reverse
UnPause Reverse

Vircaversa from reverse to forward.. It works really great... But some of the info from the the last state is "stored" in the output buffer, so I get a short playing that is wrong...

Is it any way to flush the outputbuffer?! Before unpausing another stream?!

Btw, GREAT solution on reverse playing stream, you are the best Ian!  Grin
Logged
Ian @ un4seen
Administrator
Posts: 15244


« Reply #12 on: 21 Jul '02 - 12:11 »
Reply with quoteQuote

Stopping (not pausing) a custom stream flushes it's buffer, so that's what you should do between forward/reverse playback Smiley
Logged
Largie
Posts: 110


« Reply #13 on: 21 Jul '02 - 16:51 »
Reply with quoteQuote

Quote

Stopping (not pausing) a custom stream flushes it's buffer, so that's what you should do between forward/reverse playback Smiley


Good good! Smiley This is pretty cool! Now it works almost 100%, there are some delays of turning it, but that is at most 0.2 secs or something... Smiley

Now I have moved further to make a turntable alike app, based on touch, so you can realtime "scratch" the mp3 as you like! Smiley This is really cool Ian!!!!  Grin
Logged
Pages: [1]
  Reply  |  Print  
 
Jump to:  

Powered by SMF 1.1.18 | SMF © 2013, Simple Machines