This discussion is archived
1 2 Previous Next 15 Replies Latest reply: Jul 26, 2010 4:36 PM by Miguel Angel RSS

Rewind a capture recording  in real time

Miguel Angel Newbie
Currently Being Moderated
Hi i want know how i can rewind a capture. For example the user is recording, but make and error so he press a button to rewind the recording at any point he wants, and then continue recording from that point.

this is my code for recording:

info = new DataLine.Info(TargetDataLine.class, frtoDatos);
            for (Mixer.Info e : listMixers) {
                mixer = AudioSystem.getMixer(e);
                if (mixer.isLineSupported(info)) {
                    break;
                }
            }
            if (!AudioSystem.isLineSupported(info)) {
                return;
            }
            try {
                line = (TargetDataLine) mixer.getLine(info);
                if (line != null) {
                    line.open(frtoDatos, bufSize);
                }
            } catch (LineUnavailableException ex) {
                Logger.getLogger(NuevaGrabacionAudio.class.getName()).log(Level.SEVERE, null, ex);
                return;
            }

            numBytes      = 0;
            frameSizeInBytes     = frtoDatos.getFrameSize();
            bufferLengthInFrames = lineaGrabacion.getBufferSize() / 8; 
            bufferLengthInBytes  = bufferLengthInFrames * frameSizeInBytes;
            bufferTemp     = new byte[bufferLengthInBytes];

            line.start();            
            while (!stopped) {
                if (paused) {
                    synchronized (this) {
                        while (pausado) {
                            try {
                                this.wait();
                            } catch (InterruptedException ex) {
                                Logger.getLogger(NuevaGrabacionAudio.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }
                    }
                }
                if ((numBytes= lineaGrabacion.read(bufferTemp, 0, bufferLengthInBytes)) == -1) {
                    break;
                }
                dataCaptured.write(bufferTemp, 0, numBytes);
I used an ByteArrayOutputStream: dataCaptured for its reproduction.
  • 1. Re: Rewind a capture recording  in real time
    captfoss Pro
    Currently Being Moderated
    You haven't really described enough of how you're saving the data to explain to you how to rewind the recording. You'd need to delete the end of the data, wherever you stored it... Decrement the location counter in the file/stream, essentially.
  • 2. Re: Rewind a capture recording  in real time
    Miguel Angel Newbie
    Currently Being Moderated
    The method records data from a microphone, save it into a buffer(an array of bytes), for its later reproduction when a user press a play button, and also in a file when the user press a stop button. What I want is to rewind that data stored in that buffer. For example when the user press the rewind button, I want the buffer to go back 2 seconds and the user has to listen this backforward ,as the case of the Windows Media player that you have a slider to choose from where u want to reproduce . I know i have to call the method: line.stop(), but i don`t know what i have to do.
  • 3. Re: Rewind a capture recording  in real time
    captfoss Pro
    Currently Being Moderated
    The easiest thing to do would probably be to do something like this...
    public class RewindableByteArrayOutputStream extends ByteArrayOutputStream {
    
      public void rewind(int bytes) {
        this.count -= bytes;
        if (this.count < 0)
          this.count = 0;
      }
    }
    And then just call rewind on it whenever you want to rewind it... (and obviously use that in place of your current ByteArrayOutputStream).
  • 4. Re: Rewind a capture recording  in real time
    Miguel Angel Newbie
    Currently Being Moderated
    why i have to extend from ByteArrayOutputStream?
  • 5. Re: Rewind a capture recording  in real time
    captfoss Pro
    Currently Being Moderated
    a05207811 wrote:
    why i have to extend from ByteArrayOutputStream?
    captfoss wrote:You'd need to delete the end of the data, wherever you stored it... Decrement the location counter in the file/stream, essentially.
    Because you need to do that, and the location counter for ByteArrayOutputStream is a protected variable. The only way to get access to change it is by overloading the class...
  • 6. Re: Rewind a capture recording  in real time
    Miguel Angel Newbie
    Currently Being Moderated
    the parameter:"bytes" of the rewind method do i have to pass it with this line of code?:

    bufferLengthInBytes = bufferLengthInFrames * frameSizeInBytes;
    numBytes = line.read(bufferTemp, 0, bufferLengthInBytes)
  • 7. Re: Rewind a capture recording  in real time
    captfoss Pro
    Currently Being Moderated
    a05207811 wrote:
    the parameter:"bytes" of the rewind method do i have to pass it with this line of code?:

    bufferLengthInBytes = bufferLengthInFrames * frameSizeInBytes;
    numBytes = line.read(bufferTemp, 0, bufferLengthInBytes)
    First off, that's 2 lines of code...and second off, I have no idea where you want to use the command. You should use the rewind command whenever you want to rewind the recording... and you should rewind however far you want to rewind.

    (Amount of time you want to rewind) x (frame rate of the recording) x (frame size in bytes) = what you want to pass into the rewind function
  • 8. Re: Rewind a capture recording  in real time
    Miguel Angel Newbie
    Currently Being Moderated
    For example the user is recording from the microphone Supossed I had record 10 seconds until the user press a rewind button, so the recording stop and backforward 1 second. So the recording has now 9 seconds.The user press again the rewind button and now 8 seconds and so on...
    Supossed the user wants to continue the recording from the 7 seconds. So i have to override the old recording.

    My record method is inside a Thread:
    class Recording extends ByteArrayOutputStream implements Runnable{
    
       Thread record;  
       int    frameSizeInBytes;
       int    bufferLengthInFrames;
       int    bufferLengthInBytes;
       int    numBytesRead;
       ByteArrayOutputStream dataCaptured;
       byte  bufferTemp[];
    
      public void start() {
                record = new Thread(this);
                record.start();
      }
    
    //Record method
     public void run(){
         ....
      // i got the format,the recording line and open it, 
     
        line.start();            
                while (!stopped {
                    if (paused) {
                        synchronized (this) {
                            while (paused) {
                                try {
                                    this.wait();
                                } catch (InterruptedException ex) {
                                    Logger.getLogger(Recording.class.getName()).log(Level.SEVERE, null, ex);
                                }
                            }
                        }
                    }
                    if ((numBytesRead = line.read(bufferTem, 0, bufferTemp.length)) == -1) {
                        break;
                    }
                    dataCaptured.write(bufferTemp, 0, numBytes);
                }
     }
    
    public void rewind (int nbytes){
                this.count-= nbytes;
                if(this.count<0){
                    this.count = 0;
                }
    }
    In the method rewind i supossed nbytes = numBytesRead.
    I also think that i have to put this.count instead of numBytesRead and this.buf instead of buffTemp insidme the run method. , i get confused here.
  • 9. Re: Rewind a capture recording  in real time
    captfoss Pro
    Currently Being Moderated
    Pause the recording, rewind the output stream, unpause the recording...
  • 10. Re: Rewind a capture recording  in real time
    Miguel Angel Newbie
    Currently Being Moderated
    Well the code above cut all the previous recording when i rewind, and then continue normaly. I want to be able to access at any position of the recording.

    I tried this in another way:


    public void rewind(){
    
            line.stop();
            int nBytesRead = 0;
            SourceDataLine line = null;
            DataLine.Info  info = new DataLine.Info(SourceDataLine.class,frtoDatos);
            byte audioBytes[] = dataCaptured.toByteArray();
            ByteArrayInputStream bais = new ByteArrayInputStream(audioBytes);
            audioMem = new AudioInputStream(bais, frtoDatos, audioBytes.length);
            byte[] abData = new byte[audioBytes.length];
    
            line = (SourceDataLine) AudioSystem.getLine(info);
            line.open(frtoDatos);
            line.start();
    
            try {
                nBytesRead = audioMemoria.read(abData,0,abData.length);
                audioMemoria.mark(nBytesRead - 1000);  // i mark this position to start the reproducion from here
                audioMemoria.reset();
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (nBytesRead >= 0) {
                int nBytesWritten = line.write(abData,0, nBytesRead); 
            }
    }
    in the code i also reproduce the portion of the recording from the position the user rewind until the end of the recording.

    but i can`t get to a certain position.
  • 11. Re: Rewind a capture recording  in real time
    captfoss Pro
    Currently Being Moderated
    You're having problems because you're incapable of following directions and lack the technical understanding to implement something like this.

    Please re-read what I told you to do, and please go back and do it as indicated.
  • 12. Re: Rewind a capture recording  in real time
    Miguel Angel Newbie
    Currently Being Moderated
    sorry but i am new at java sound. I am putting the code here and can you tell me what are the wrong lines i have to change??
    class Grabacion extends ByteArrayOutputStream implements Runnable {
    
      //declarations...
    
    
    //method that records
    
    public void run(){
    lineaGrabacion.start();            
                while (!detenido) {
                    if (pausado) {
                        synchronized (this) {
                            while (pausado) {
                                try {
                                    this.wait();
                                } catch (InterruptedException ex) {
                                    Logger.getLogger(NuevaGrabacionAudio.class.getName()).log(Level.SEVERE, null, ex);
                                }
                            }
                        }
                    }
                    if ((numBytesLeidos = lineaGrabacion.read(this.buf, 0, this.buf.length)) == -1) {
                        break;
                    }
                   this.write(this.buf,0,numBytesLeidos);
                   calcularVolumen(buf, 0, buf.length);
               }
    
    
    
    }
  • 13. Re: Rewind a capture recording  in real time
    Miguel Angel Newbie
    Currently Being Moderated
    my method rewind wil be something like this:
    public void rewind(){
        in nbytes = (int) (1000 * frtoDatos.getFrameRate() * frtoDatos.getFrameSize()); 
        this.count-= nbytes;
        if(this.count<0){
          this.count = 0;
         }
  • 14. Re: Rewind a capture recording  in real time
    captfoss Pro
    Currently Being Moderated
    a05207811 wrote:
    sorry but i am new at java sound. I am putting the code here and can you tell me what are the wrong lines i have to change??
    It has nothing to do with being new at JavaSound, it has to do with being new to programming in general and being a poor listener.

    You were told to replace the default ByteArrayInputStream that you're using and replace it with an extended version with a rewind function in place. How you took that meant your main class needed to extend ByteArrayInputStream is beyond me...

    But just for the sake of clarity...
    1) Your main class should not be extending ByteArrayInputStream
    2) You will need to create a brand new class that (a) extends ByteArrayInputStream (b) provides a rewind function
    3) Your main class should make use of the new class, and should not be using the default implementation of ByteArrayInputStream...
1 2 Previous Next