Author Topic: How to record from a Stream which has been modified its speed. [SOLVED]  (Read 2294 times)

_Andrew

  • Posts: 4
Hello everyone.

  I have been developing an mp3 player, and I cant solve this problem by myself. I will try to explain it:

    The mp3 player includes some funcionalities, such as 3-Band Equalizer, Balance, Speed ... etc... and also a button for recording a song which is beign played. When the user press the record button, It works correctly, and the programm records the playing song, also including the 3-Equalizer and Balance modifications that the user performs on live.

    But my problem is that the programm never records the SPEED changes performed by the user. So when the user plays a song, press 'record' and modifies the speed, it sounds correctly (with the speed changed), but it records the song with its default speed, without taking into account the user speed changes.


    Here I paste the code Im using for change the speed and also the code Im using for start and stop recording:

Note: The stream definition Im using for the methods above is:
Code: [Select]
stream = Bass.BASS_StreamCreateFile(ruta, 0, 0, BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_PRESCAN);
         Method for Setting the Speed:
Code: [Select]
               ...
                Bass.BASS_ChannelSetAttribute(stream, BASSAttribute.BASS_ATTRIB_FREQ, speed);
                ...

         Method for start recording the playing stream:
Code: [Select]
       public Boolean recStart()
        {
            l = new EncoderLAME(stream);
            l.InputFile = null; //STDIN
            l.OutputFile = "./SND/output.mp3";
            l.LAME_Bitrate = (int)EncoderLAME.BITRATE.kbps_192;
            l.LAME_Mode = EncoderLAME.LAMEMode.JointStereo;          
            ...
                l.Start(null, IntPtr.Zero, false);    
            ...

        }

         Method for stop recording the playing stream:
Code: [Select]
               ...
                l.Stop();
                Bass.BASS_ChannelGetData(stream, encBuffer, encBuffer.Length);
                ...

    If someone could tell me any idea about why this code is not recording the song with the speed changes I would be very grateful.

  Thanks everyone: Andrs.
« Last Edit: 15 Feb '12 - 10:41 by _Andrew »

Smoov

  • Posts: 13
Have you considered passing the stream(s) through a mixer?

We do this to perform overlap of multiple files and perform tempo changes to these files. This methods works pretty good to capture what you would hear.

Also if you you the tempo feature in bass-fx, you can perform pitched and un-pitch speed changes.


radio42

  • Posts: 4576
The reason why you don't hear anythins is, that the BASS_ATTRIB_FREQ flag is used by the device driver.
As the docs say: This attribute applies to playback of the channel, and does not affect the channel's sample data itself!
That's why any 'recording' doesn't 'see' this attribute change.

As "Smoov" pointed out. Using a BASSmix mixer stream or a BASS_FX tempo stream would to the job.

_Andrew

  • Posts: 4
Thank you very much.

  Sorry my ignorance respect this library, but Im trying to use a Mixer in order to record the Frequency changes but I dont know exactly how to rewrite the code.

  ʹm trying to solve using now this new modifications:

        'stream' continues beign the handler Im using for playing. Now Im trying to use a BassMix to record with speed changes:

Code: [Select]
        int mixer;

         mixer = BassMix.BASS_Mixer_StreamCreate(44100, 1, BASSFlag.BASS_SAMPLE_FLOAT);

         BassMix.BASS_Mixer_StreamAddChannel(mixer, stream, BASSFlag.BASS_DEFAULT);
        
         //Bass.BASS_ChannelPlay(mixer, false);  //  Im not sure if MixChannel should be played.. But Ive tryed too..


            l = new EncoderLAME(mixer);
            l.InputFile = null; //STDIN
            l.OutputFile = "./SND/output.mp3";
            l.LAME_Bitrate = (int)EncoderLAME.BITRATE.kbps_192;
            l.LAME_Mode = EncoderLAME.LAMEMode.JointStereo;

          Bass.BASS_ChannelGetData(mixer, encBuffer, encBuffer.Length);

    Now, the problem is that when I check the encBuffer, it is empty, like if no sound had been recieved. What am I doing bad ?

    Thanks everyone for your help.

Ian @ un4seen

  • Administrator
  • Posts: 20437
Please check the return value of each BASS function call, and if any is failing, use BASS_ErrorGetCode to get the error code and look that up in the failed function's documentation to find out what went wrong. I suspect the BASS_Mixer_StreamAddChannel call may be failing. Have you added the BASS_STREAM_DECODE flag to your BASS_StreamCreateFile call?

_Andrew

  • Posts: 4
Thanks 'Ian @ un4seen'.

  Ive checked the ErrorCode and it returns BASS_ERROR_DECODE.

  Now Ive tryed to setup the initial stream as:

Code: [Select]
stream = Bass.BASS_StreamCreateFile(ruta, 0, 0, BASSFlag.BASS_STREAM_DECODE);
  But with DECODE flag it doesnt sounds !  So now my problem is How can I declare the stream in order to sound normally, and also use a Mixer to record its sound with the speed modifications.

  I have checked also if it records at least, but although the BassMix.BASS_Mixer_StreamAddChanne returns true; and the buffer contais data, it doesnt records any audio !

  Im so close to the solution !

  Thanks again.

Ian @ un4seen

  • Administrator
  • Posts: 20437
  But with DECODE flag it doesnt sounds !  So now my problem is How can I declare the stream in order to sound normally, and also use a Mixer to record its sound with the speed modifications.

Unfortunately, it isn't possible to use a single BASS channel for both normal playback (eg. via BASS_ChannelPlay) and playback via a mixer. If you would like to switch between the two, you will need to call BASS_StreamCreateFile again with/without the BASS_STREAM_DECODE flag. Another option is to do all playback via the mixer, not only when writing a file.

_Andrew

  • Posts: 4
[SOLVED]
« Reply #7 on: 15 Feb '12 - 10:38 »
Thanks EveryBody !!

  I have finally solved the problem thanks ur knowledge !  I just used the BASS addon FX to the whole application. So I can now play, do any modification and record the audio. Please find here my final code in order to help any other person could be stucked at the same point:

Inicialization:
Code: [Select]
            Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero);

            streamFile = Bass.BASS_StreamCreateFile(ruta, 0, 0, BASSFlag.BASS_STREAM_DECODE);

            ActiveStreamHandle = stream = BassFx.BASS_FX_TempoCreate(streamFile, BASSFlag.BASS_FX_FREESOURCE);

Playing[:/b]
Code: [Select]
            Bass.BASS_ChannelPlay(stream, false); // start playing
Modifying the speed:
Code: [Select]
        public void setSpeed(float s)
        {
            speed = s;
            if (stream != 0)
            {
                Bass.BASS_ChannelSetAttribute(stream, BASSAttribute.BASS_ATTRIB_TEMPO, speed);
            }
        }

Recording:
Code: [Select]
            //  Start recording...
            l = new EncoderLAME(stream);
            l.InputFile = null; //STDIN
            l.OutputFile = "./SND/output.mp3";
            l.LAME_Bitrate = (int)EncoderLAME.BITRATE.kbps_192;
            l.LAME_Mode = EncoderLAME.LAMEMode.JointStereo;

            ...
            //  Stop recording...
            Bass.BASS_ChannelGetData(stream, encBuffer, encBuffer.Length);


  Thanks all the help and support given to me. Regards.
« Last Edit: 15 Feb '12 - 10:40 by _Andrew »