quinta-feira, 27 de dezembro de 2012

Brincando com transformações de BMP em WAV

Todo arquivo é um punhado de bytes. O que faz ele ser imagem, texto, som ou vídeo é a forma como estes bytes estão organizados. Mas nada impede de pegar os bytes de um arquivo e "enganar" o computador dizendo para ele que é outro arquivo. Isto pode ser feito simplesmente alterando o cabeçalho do arquivo.
Bem, fiz 2 programas: um que coloca cabeçalho BMP e outro que coloca cabeçalho WAV.
De forma geral podemos pensar que ele converte qualquer coisa em imagem e outro que converte em som.
Depois eu testei com várias coisas: PDF, doc, MP3, imagens, textos, ...
E o que ficou mais legal de ouvir foram arquivos de log do sistema operacional. Talvez por serem "periódicos".
Escolhi um arquivo de log. Depois de ouvir e achar legal, converti em imagem, abri o gimp e mudei a imagem na mão. A cada alteração eu gerei o som correspondente. Editado no Gimp ele foi se transformando em novos sons.

Depois juntei imagem e som em um vídeo.
















C ANSI arquivos para wave

Já teve vontade de "ouvir" fotos, arquivos PDFs e coisas assim? Ok, não é exatamente útil mas sim, pode ser divertido.

gcc towav.c -o towav e Voilá!




#include <sys/stat.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>


int main(int argc, char ** argv){

   if(argc < 4){
      printf("Usage:\n");
      printf("%s sample_rate bit_depth\n", argv[0]);
      exit(0);
   }

   char * filename = malloc(strlen(argv[1]));
   strcpy(filename, argv[1]);

   struct stat st;
   stat(filename, &st);
   uint32_t size = st.st_size; //limita o tamanho do arquivo!
   printf("filesize: %d\n", size);

   // Read file data
   char * buffer = 0;
   FILE * f = fopen (filename, "rb");
   buffer = malloc(size);
   fread (buffer, 1, size, f);
   fclose (f);

   char * newfilename = malloc(strlen(argv[1] + 4));
   strcpy(newfilename, filename);
   strcat(newfilename, ".wav");
   FILE *fp = fopen(newfilename,"wb+");

   fwrite("RIFF", 1, 4, fp);
   int newsize = size + 32; // file size - 8
   fwrite(&newsize, 1, sizeof(newsize), fp);
   fwrite("WAVE", 1, 4, fp);

   fwrite("fmt ", 1, 4, fp);
   int flag = 16; // chunk size
   fwrite(&flag, 1, 4, fp);
   flag = 1; // compression code
   fwrite(&flag, 1, 2, fp);
   flag = 1; // number of channels
   fwrite(&flag, 1, 2, fp);
   flag = atoi(argv[2]); // sample rate
   fwrite(&flag, 1, 4, fp);
   flag = flag * atoi(argv[3]) / 8; // bytes per second
   fwrite(&flag, 1, 4, fp);
   flag = atoi(argv[3]) / 8; // block align
   fwrite(&flag, 1, 2, fp);
   flag = atoi(argv[3]); // significant bits per sample
   fwrite(&flag, 1, 2, fp);

   fwrite("data", 1, 4, fp);
   fwrite(&size, 1, 4, fp);

   fwrite(buffer, 1, size, fp);
   fclose(fp);

}

Algumas referências:



O dmesg ficou muito bom tocado a 10025 com 8 bits!

terça-feira, 20 de novembro de 2012

Apagando redes do Ubuntu

O Ubuntu tem mapeada várias redes que já conectei mas tinha uma que estava incomodando. Algo como 100 conexões em um mesmo nome e impossível apagar na mão. Vamos para o terminal.

Encontrei os arquivos de conexões disponíveis a todos os usuários no diretório

/etc/NetworkManager/system-connections/

Elas estão bonitinhas, com os nomes de suas redes. Prontas para serem apagadas em série. Claro que precisa do sudo.

Além disto, há os arquivos de configuração para as conexões não compartilhadas com todos os usuários em


~/.gconf/system/networking/connections


Não tão fáceis mas nada que um grep não resolva:



grep -c Nome */*/* | grep :1

Com isto temos o nome dos diretórios que possuem informação sobre esta conexão de nome "Nome",

Sim, estou bem mais feliz agora.

Fonte:

terça-feira, 23 de outubro de 2012

Seus 3 desejos


A fábula do gênio da lâmpada é conhecida e acredito que todos saberiam o que desejar. Pelo menos o último desejo. Qualquer um que já perdeu a sua inocência da infância sabe que seu último desejo deve ser mais 3 desejos. Ou infinitos. Assim não precisamos nos preocupar com o que desejamos. Podemos sempre desejar mais e mais e sermos felizes realizando nossos desejos para sempre.

Mas será que só 3 desejos não bastam? Claro que isto traz um problema. Pensar direito, desejar direito, ponderar sobre o que realmente vale a pena e pedir que o desejo seja realizado. Deveríamos acreditar que temos apenas 3 desejos. Pensar mais sobre o que realmente queremos. Talvez apenas um desejo pudesse bastar. Talvez seja da natureza do homem não saber o que realmente quer e querer sempre desejar mais.

Pergunto se este desejo não é egoísta. Sim, egoísta. Ora, se seus desejos acabam, a lâmpada apareceria para outra pessoa e esta também teria 3 desejos, certo? Ao desejarmos o gênio para sempre impedimos outras pessoas de também realizarem seus desejos. Esta é a razão de eu achar isto egoísta.

Você deve estar se perguntando se eu endoidei ou se voltei a ler livros da minha infância. Ainda não. Comecei com esta conversa de gênio da lâmpada pensando superficial sobre desejos e mais desejos. Isto não importa. Afinal de contas, isto é só uma fábula, certo?  Onde esta conversa pode nos levar? Bem, voltemos ao mundo real: estou falando de reeleição.

Um candidato pode fazer um ótimo mandato em quatro anos. Não acredito que alguém tenha tanto a desejar e fazer por uma cidade que não consiga fazer em quatro anos. Foi este plano de governo em 4 anos que o elegeu. Se cumprisse seu plano de governo de quatro anos, quatro anos deveriam bastar. Mas não bastam. Sempre há um último desejo que nossos políticos pedem para o genial povo brasileiro: mais 4 anos.

Se ele não pode se reeleger ele coloca a esposa, o irmão, o vice, o filho, o pai, o avô. E tentam passar a lâmpada mágica para alguém muito próximo quando seus desejos acabam. Não querem que alguém de outro partido tenha desejos. Alguém de outro lugar da cidade. Acreditam ou nos fazem acreditar que a felicidade alheia pode atrapalhar a sua própria felicidade. Não querem liberar o gênio, digo, o povo e tentam guardar a lâmpada mágica do poder para si e para os seus.

Acho que você já percebeu que eu sou contra reeleição. Sou contra as capitanias hereditárias na política brasileira. Pense bem. Reeleição não é só reeleger o mesmo candidato. Inclua nisto o irmão, o pai, o neto, o tio, o vice, a esposa e quem mais puder. Todas estas pessoas poderiam ter ajudado nos quatro anos. Eles estavam lá durante o mandato, tiveram a chance de governar com o candidato eleito. Se não fizeram antes, porque farão agora? O que mais este mesmo grupo pode desejar para nossa cidade que não pôde ser feito em quatro anos?

Somos o gênio da lâmpada mas podemos ler a lista de desejos antes de escolher a quem servir. Isto chama-se proposta de campanha. A eleição é um processo democrático que nos permite escolher a melhor proposta. Uma proposta que caiba em quatro anos de mandato. Se na proposta aparecesse: Meu último desejo é mais 3 desejos, eu, como gênio, não serviria a este senhor.

Um outro candidato, nem tão preparado, nem tão conhecido, não tão bem aconselhado talvez tenha alguns desejos bons para a cidade. Talvez este desejo não afete minha vida diária. Com certeza, afetará a de alguém. É justo. É democrático. Outras pessoas deveriam ter o direito de governar. A cidade não é só de seu candidato.

Provavelmente você também desejaria mais 3 desejos se pudesse. Acho que eu faria o mesmo. Só que no caso das eleições, não é uma fábula. E aqui não é você que deseja. Você é o gênio que dá o poder para quem deseja se eleger. Como gênio, por quanto tempo você quer servir ao mesmo senhor?

segunda-feira, 1 de outubro de 2012

Passagem de parâmetros em C


Ao criamos uma função podemos passar parâmetros. Estes parâmetros podem ser passado de algumas formas mas as mais clássicas são por valor ou por referência. Para entender o que é isto teremos de dar uma olhadinha na pilha memória do computador. Começamos definindo funções que recebem inteiros. Serei um tanto simplista no meu exemplo e espero que isto não atrapalhe o entendimento.

Definiremos 3 funções: uma recebe o parâmetro por valor e retorna o resultado e outra por referência, ou seja, ponteiros, e retorna o valor e outra recebe por referência e não retorna nada.

int soma_valor(int x, int y){
   return x + y;
}

int soma_referência1(int * x, int * y){
   return *x + *y;
}

void soma_referência2(int * x, int * y){
   *x = *x + *y;
}

main(){
   int a = 3;
   int b = 5;

   soma_valor(a,b);
   soma_referência1(&a, &b);
   soma_referência2(&a, &b);
}

Bem, vamos ver o que acontece na nossa pilha quando executamos o programa main.

O Sistema operacional (SO) irá alocar espaço para a variável a e vai guardar o valor 3. Depois ele vai guardar espaço para a variável b e vai guardar o valor 5.

Ao chamarmos a função soma_valor, ele vai alocar outros espaços para outras variáveis x e y (que também poderiam chamar a e b ou qualquer outro nome. Mudei o nome só para facilitar a explicação) e vai copiar o valor de a para x e de b para y. O sistema vai alocar também uma variável sem nome para o retorno da função. Temos neste ponto alocados na memória 5 inteiros: a, b, x, y e retorno. A função executa, libera a memória das variáveis x, y e retorno e retorna o valor. Não estamos fazendo nada com o retorno dela mas ela retorna.
Custo total: alocação de 5 variáveis, calcular o resultado da soma e cópia de memória de a para x, b para y e resultado da soma para o retorno.

Na próxima função, alocamos apenas o inteiro para o retorno. A chamada da função irá receber um ponteiro, ou seja, o endereço alocado previamente (indicado pelo &) das variáveis a e b e não precisará alocar espaço para seus valores e nem copiar os valores de uma região da memória para outro. Internamente ela pega o valor que está neste endereço (indicado pelo *), soma, copia o valor da soma para o retorno e retorna. Com certeza isto é mais barato pois no final teremos alocado apenas o valor de um inteiro para o retorno.
Custo total: Alocação de 1 variável retorno, calcular o resultado da soma e cópia do resultado da soma para o retorno.

Na terceira e última função, não alocamos valor nenhum da memória. A função receberá o endereço das variáveis previamente alocadas, irá copiar o valor da soma para o endereço de memória da variável a (que internamente na função é chamado de x) e não precisa retornar. Neste caso, no término da função o valor da variável a será 8 e não mais 3. Isto evita a alocação da variável de retorno mas irá perder para sempre o valor inicial de a. Isto pode ser bom ou ruim, dependendo do objetivo do programa.
Custo total: Calcular o resultado da soma.

Agora, imagine que este programa seja o processamento de um vídeo e vc esteja somando 2 vídeos de 2 GB cada. Na primeira função, temos a alocação de 5 variáveis que somadas ocuparão 10GB da memória. No segundo exemplo ocuparemos apenas 6GB de memória e no terceiro apenas 4GB de memória, o que é o custo mínimo já que os mesmos precisarão ser carregados. Acho que dá para começar a sentir a diferença de desempenho destas funções que fazem a mesma coisa mas que fazem de forma diferente...

No primeiro exemplo temos a cópia da memória de 4GB das variáveis a e b para x e y. Quanto tempo isto leva? E se esta função for chamada 10 vezes em um segundo? Dá para fazer isto em "tempo real"? No segundo exemplo não perdemos tempo copiando os valores de entrada mas precisamos copiar o valor para a variável de retorno. Já é mais eficiente. No terceiro podemos fazer a soma diretamente no endereço de a (que internamente na função é chamado de x) e esta soma pode ser feita "in loco". Com certeza mais eficiente.

Alguns textos que tem exemplos mais bonitos que o meu:



Agradeço ao Rael que me mandou a dúvida e que rendeu este texto.

Entendendo orientação a objetos


Praticamente toda linguagem de programação estruturada possui a capacidade de definirmos estruturas de dados. Uma estrutura de dados é um tipo de dado composto definido pelo usuário. Assim, podemos definir um tipo Pessoa que possui um nome e uma idade. Sei que este exemplo não é nada útil mas vou usá-lo mesmo assim. Isto é uma estrutura de dados. Em C definimos como struct e em pascal como um record. Em C fica assim:

struct {
     char * nome;
     int idade;
} pessoa;

Ao criarmos uma estrutura de dados é como se criássemos um novo tipo de variável que pode ser usada em nosso programa. Bem, podemos então instanciar uma variável do tipo pessoa da mesma forma que instanciamos uma variável do tipo inteiro ou float. Assim:

int a;
float b;
pessoa c;

Ao usarmos esta variável é possível acessar os dados encapsulados pelo tipo. Desta forma é possível acessar o nome e a idade do tipo pessoa diretamente:

pessoa c;
c.idade = 20;
c.nome = "Antonio";

Além da possibilidade de criarmos estruturas de dados, as linguagens costumam permitir que criemos fuincionalidades. Assim é possível definirmos uma função gravar que irá gravar uma pessoa. O tipo de dado pessoa pode ser passado diretamente para a função que irá conhecer este tipo de dado da mesma forma que conhece um inteiro, float ou char:

/* Exemplo que recebe dois inteiros */
int somar(int a, int b){
     return a + b;
}

/* Exemplo que recebe uma pessoa */
int gravar(pessoa p){
     /* Grava de alguma forma em arquivo ou banco de dados
     p.nome;
     p.idade;
     */
     return 1;
}


Bem, o que a orientação a objetos traz de diferente é a possibilidade de definirmos as funcionalidades junto com a estrutura de dados. A este conjunto de estrutura de dados (que chamamos de propriedades) e funcionalidades (que chamamos de métodos) chamamos classe. Seria o mesmo que definir em uma struct algo assim:

struct {
     char * nome;
     int idade;
     int gravar_pessoa(){
     /* Grava de alguma forma */
     /* this.nome; */
     /* this.idade */
     return 1;
     }
} pessoa;

NOTE QUE ESTE EXEMPLO NÃO FUNCIONA!

Ao adicionarmos a funcionalidade a estrutura de dados, podemos acessar o método (função) da mesma forma que acessamos os atributos ou propriedades.

pessoa p;
p.nome = "Maria";
p.idade = 23;
p.gravar();


Veja que o método gravar pertence a instância da variável e por isto ele consegue acessar internamente suas propriedades. E isto é orientação a obejtos. Costumo dizer que OO é uma questão de escopo. De maneira muito simplista é fechar a chave que define a estrutura de dados depois de definirmos as funcionalidades. :-) Só que em vez de definirmos esta estrutura como uma struct (que o próprio nome indica ser APENAS estrutura de dados) definimos como uma classe.

Se Orientação a objetos fosse apenas isto, já seria muito legal. Mas OO é bem mais que isto.

Polimorfismo


Na maioria das linguagens, não podemos definir duas funções com o mesmo nome. Se tivermos um sistema que possui as estruturas de dados pessoa, usuário, aluno, livro e empréstimo teremos de ter funções com nomes diferentes para gravar pessoa, usuário, aluno, livro e empréstimo. Cada uma delas receberá um tipo de dado definido anteriormente e que a função sabe como tratar.

int gravar_pessoa(pessoa p){ /* ... */}
int gravar_usuário(usuário u){/* ... */}
int gravar_aluno(aluno a){/* ... */}
int gravar empréstimo(empréstimo e){ /* ... */}


Agora é possível termos vários métodos gravar, um para pessoa, outro para livro e outro para aluno. E isto tem nome, chama-se polimorfismo. Polimorfismo nada mais é que métodos com o mesmo nome em classes diferentes, no caso gravar, que fazem coisas diferentes, no caso gravar coisas diferentes.

Encapsulamento

Orientação a objetos também permite acessos distintos a estrutura de dados. Podemos ter dados privados, que apenas a própria classe pode acessar ou dados públicos que qualquer dado pode acessar. Isto não existe na programação estruturada e é bem útil para dados internos e de controle.

Assim, sua estrutura de dados não fica "exposta" indevidamente e você pode definir diferentes níveis de acesso para as propriedades e também para os métodos. Diria que com isto a programação em equipe fica mais organizada.

Herança

OO também permite que uma classe complemente os dados de outra. Assim, temos uma estrutura de dados chamada usuário que possui apenas login e senha e temos uma estrutura de dados chamada aluno que irá estender usuário e só por estender já ganha os atributos login e senha.

O método logar também será herdado e este método usará apenas os dados do usuário, que o aluno já herdou.


class Usuário {
   char * login;
   char * senha;
public:
   int logar() { /* ... */  }
};

class Aluno : public Usuário { /* ... */ };

 int main() {
   Aluno a;
   a.logar();
}

Conclusão

Orientação a objetos é bem legal!

quinta-feira, 16 de agosto de 2012

Transformando o Windows em uma máquina útil

Baixe o Mingw:

http://sourceforge.net/projects/mingw/files/

Aceite, selecione os compiladores e o sistema.

 Instale.

Baixe o GnuWin:

http://sourceforge.net/projects/gnuwin32/

Aceite. Instale.

 Coloque ambos no PATH to Sistema:

Control Panel -> System -> Advanced System Settings -> Environment Variables

Edite a variável PATH e adicione no final da mesma:

;C:\MinGW\bin;C:\Program Files (x86)\GnuWin32\bin

Teste se funcionou. Abra um terminal e escreva.

gcc -- version

make --version




quarta-feira, 25 de julho de 2012

Executando o PD extended com o Pulse Audio

Subir o PD extended (ou simplesmente o PD) com o pulseaudio pode ser um problema. Muitas vezes o PD não consegue alocar a placa de som e temos o PD funcionando sem som.

Para resolver isto, é necessário utilizar a linha de comando e chamar o padsp. Resolve:

padsp pdextended

quarta-feira, 16 de maio de 2012

Instalando o netperf

No MacOS

Faca o download da versão mais nova em zip em

ftp://ftp.netperf.org/netperf/

descompacte. Entre na pasta e digite

./configure

make

sudo make install

No Linux

sudo apt-get install netperf
Para executar:

Este programa mede a largura de banda entre duas máquinas, A e B. Na máquina A execute o servidor:




netserver -4

A opção -4 é para utilizar o endereço no formato IPV4.

No cliente, alguns testes possíveis, supondo que a máquina servidor tenha o IP 192.168.1.119:

netperf -H 192.168.1.119 -t UDP_STREAM -D 0.5 -l 5 -f M
netperf -H 192.168.1.119 -t TCP_STREAM -l 5 -f M
netperf -H 192.168.1.119 -t TCP_RR -v 2
netperf -H 192.168.1.119 -t TCP_RR -v 2

Opções:
-H indica o IP do servidor
-t tipo do teste
-l duração do teste em segundos
-f formatação do resultado (MB)



Fonte:

http://www.tonymacx86.com/viewtopic.php?t=5700


Mais informações, consulte o manual:
http://www.netperf.org/svn/netperf2/tags/netperf-2.5.0/doc/netperf.html

Auto Tunning no Linux

No Windows e Mac acho que todo mundo já conhece alternativas como o AutoTune da Antares e o Melodyne da Celemony. Bem, para os que não querem tomar wine na cabeça seguem 4 dicas:


VocProc: Possui 2 entradas, uma para a carrier do vocoder e outra para o formante.
zita-at1: Foi feito pelo Fons e roda pelo Jack. Tem uma GUI super simples e aceita entrada MIDI. Não possui correção de formante e se perder um pouco em correções muito grandes.


Autotalent: Plugin LV2. Tem correção de formante.

 Vocoder: Plugin LV2. Não é um auto tunner, certo? Se todos não fosse um vocoder...

Transformando o Mac em uma máquina útil

Com o CD 2 original, instalei  o tal XCode. Isto leva tempo e não resolve pois é uma versão antiga. Inicia-se uma saga....

Na AppStore o XCode é grátis mas apenas para a ultima versão do MacOS. Fantástico!

Para baixar a versão antiga é necessário se registrar. Para o registro é possível pagar US$99, US$150, US$250 e outros valores mas também é possível se registrar de graça se você for estudante. Para se registrar como estudante vc precisa informar o email de um professor e estará assinando um contrato de parceria entre sua universidade e a Apple. Fantástico, fantástico!

Descobri que é possível entrar na seção de desenvolvedores com um ID do itunes, que precisa apenas de seu email, nascimento e outros dados pessoais que provavelmente serão usados de forma irregular pela Apple. Fantástico, fantástico, FANTÁSTICO!

Registrei-me no itunes e baixei o XCode. Mais de 4GB de download....

Agora só falta instalar o Ports.

http://www.macports.org/

É isto.

sexta-feira, 13 de abril de 2012

RTSKED





Medindo a bateria com o Linux

Baterias são um problema. Veja como medir a bateria no Linux (via console, claro).

Instale um pacote chamado acpi e rode:

acpi -V

com o man, podemos ver outras opções:

acpi -i

E o resultado:

Battery 0: Full, 100%, rate information unavailable
Battery 0: design capacity 8800 mAh, last full capacity 1152 mAh = 13%

Outra maneira de fazer isto é com o comando:

grep -F capacity: /proc/acpi/battery/BAT0/info
 
Resultado:

design capacity:         8800 mAh
last full capacity:      1152 mAh

Ou seja, hora de trocar de bateria...

Fontes:

terça-feira, 28 de fevereiro de 2012

Enscribe - Imagem para som

Encontrei um software no mínimo curioso para Linux. Chama-se enscribe e transforma imagens em sons. Os sons também são bastante curiosos principalmente se criados a partir de fotos curiosas...

enscribe.

Depois vou olhar com mais carinho e arrumar este post.

Extrair áudio de vídeo AVI

Este é bico:

ffmpeg -i my_video_file.avi extracted_audio.mp3

 E como tudo no universo Linux tem mais de um comando:

mplayer -dumpaudio my_video_file.avi -dumpfile extracted_audio.mp3
 
 
Fonte:
 
http://www.dailygyan.com/2008/01/how-to-extract-audio-from-any-video.html

sexta-feira, 13 de janeiro de 2012

APIs para desenvolvimento de software com áudio

Desenvolver uma aplicação que pode ser usada diretamente sobre a camada de áudio do SO é confusão. O Windows tem o DirectSound, WinKS, WASAPI, Windows Multimedia Library e ASIO, o Linux tem o FFADO, ALSA e OSS e o MacOS tem o Sound Manager, ASIO e Core Audio. Implementar um software que funcione em tudo isto pode ser transtorno.

Encontrei algumas alternativas que parecem ser viáveis: JUCE, SDL, OpenAL, RTAudio e PortAudio. Basicamente tratam-se de 3 APIs abertas que permitem escrever aplicações de áudio e compilá-la para aquela lista acima.

  • O JUCE (http://www.rawmaterialsoftware.com/juce.php)  promete atender até implementações de Audio Unit (plugins tipo VST para Mac) e VST. Além disto possui biblioteca para GUI. Por isto pareceu um quase Qt.

  • O SDL (http://www.libsdl.org/) permite acesso também ao teclado, webcam, mouse e outras coisas. É dirigido para jogos. Não me convenceu apesar de ser uma alternativa para futuramente incluir stream de vídeo. Se não estou enganado possui biblioteca para Arduino. E ATARI!

  • O openAL foi feito pela creative e pode ser uma alternativa para trabalhar com  espacialização. Pareceu-me que ela foi feita para isto.  É uma API para multicanais de saída muito utilizada para jogos, por exemplo (http://connect.creativelabs.com/openal/OpenAL%20Wiki/Games.aspx). Pra ajudar, parece que funciona em Android. Pelo que li, não possui suporte ao MIDI.

  • O RTAudio foi feito por um tal Gary Scavone, na época no CCRMA em Stanford (https://ccrma.stanford.edu/software/stk/index.html)  e atualmente na universidade de McGill (http://www.music.mcgill.ca/~gary/rtaudio/). Lembro de ter visto ele no código do Jacktrip. Acho que o jacktrip, talvez por ter sido feito no mesmo CCRMA, usa ou usava-o. Esta API tem um problema que é ter o mesmo nome de uma API da Microsoft. :-)

  • O PortAudio me pareceu a API mais madura. Pd, CSound e Audacity, por exemplo, estão em PortAudio (http://www.portaudio.com/apps.html). Parece funcionar bem.
Resumindo, preciso ler mais sobre isto...

quarta-feira, 4 de janeiro de 2012

Extrair áudio de um DVD

Listar o conteúdo de um DVD

lsdvd

Extrair as 99 faixas de áudio para mp3

for((x=1; x<=99; x++)) do
mplayer dvd://0$x -cdrom-device /dev/sr0 -dumpaudio -dumpfile track$x.mp3; 
done;


Mas se ele estiver separado em capítulos e não em títulos


for((x=1; x<=99; x++)) do
mplayer dvd://01 -chapter $x-$x -cdrom-device /dev/sr0 -dumpaudio -dumpfile track$x.mp3; 
done;


Fontes:
  • http://www.cyberciti.biz/faq/linux-unix-extract-audio-from-avi-video-file-online-stream/
  • http://www.mplayerhq.hu/DOCS/HTML/en/faq.html#idp11189712
  • http://lists.mplayerhq.hu/pipermail/mplayer-users/2003-April/032217.html