cat /dev/null

Tulip - tablaturas à partir da boa e velha cifra numérica

Criei esse programa há uns 6/7 anos atrás por uma necessidade... precisava passar umas músicas que tinha anotadas em cifra numérica para tablatura, pois o negócio aqui estava feio, tinha acumulado muitos papéis com anotações de músicas que fui tirando ao longo dos anos.

Originalmente fiz ele no Linux mas depois portei uma versão para Windows também.

Hoje em dia muita gente que começa não aprende essa notação, uma pena porque ela é bem prática, mas passá-la para tablatura é muito cansativo e chato.

Pois bem, cifra numérica é isso aqui (a boa e velha escala cromática):

60-61-62-63-64-
50-51-52-53-54-
40-41-42-43-44-
30-31-32-33-34-
20-21-22-23-24-
10-11-12-13-14-|

O que o tulip faz é pegar uma música expressa nesses moldes e gerar a tablatura.

Chega de conversa, aproveitando o mês das bruxas vai aí o riff de "Burn The Witch" do "QoTSA" em linguagem "Tulip".

Vamos criar uma arquivo "burn_the_witch.tlp" em "C:\tulip"


  1. _brainbox=

  2. CUT_TAB_TO_SAVE=yes;

  3. ;_brainbox



  4. _headbox=

  5. Burn The Witch Riff (QoTSA)

  6. Tunning C drop



  7. ;_headbox



  8. _bodybox=

  9. .quote{"\n\nIntro\n\n"}

  10. .chord{64-56-46}-.chord{64-56-46}.repeat{3}-;

  11. .quote{"\n\nMain riff\n\n"}

  12. .chord{64-56-46}-.chord{64-56-46}-|-34-46-44-|-

  13. .chord{64-56-46}-.chord{64-56-46}-|-44-56-54-67-;

  14. ;_bodybox



  15. _tailbox=



  16. That's all folks!

  17. ;_tailbox





Pronto, com a música codificada tudo que precisamos é entregar ao tulip o arquivo para que ele gere o arquivo ".txt" com a tablatura. O tulip estando instalado em "C:\Tulip", no prompt de comando digite:

tulip burn_the_witch.tlp burn_the_witch.txt

Pressione ENTER, ele vai compilar seu código se tudo estiver ok, como você forneceu um segundo nome de arquivo, ele cria a tab com esse nome. Então "burn_the_wicth.txt" contém
a notação em tablatura de um riff foda! :)

Se você colocar "C:\Tulip" na variável de ambiente "PATH" poderá chamá-lo dentro do prompt de comando à partir de qualquer pasta.

Esse software me foi bem útil na época e confesso que ainda hoje é ele que uso para passar minhas transcrições para o PC.

O maior desafio e diversão foi criar algo que pudesse expressar computacionalmente a cifra numérica, como na época estava usando muito o LaTeX, aquelas macros TeX acabaram sendo uma inspiração.

No exemplo passado não deu para mostrar, mas o Tulip possui um aspecto recurssivo em sua sintaxe o que permite a combinação de tags para expressar combinações de técnicas, imagine um palm mute do acorde E na 7ª casa da guitarra:


  1. .mute{

  2. .chord{57-49-39-29}-

  3. .chord{57-49-39-29}-

  4. .chord{57-49-39-29}

  5. }



Como desenvolvedor pude finalmente usar recurssividade para um problema mais prático, foi legal a ver a utilidade do conceito indo além daqueles fatoriais idiotas que todo mundo um dia já precisou fazer. Já parou para pensar como a recurssividade está em tudo na computação? E até fora dela... mas enfim deixa isso para outra hora...

Teve um outro recurso que depois coloquei, foi o de filtrar as infos básicas de um MIDI gerando o código Tulip e dele a tablatura. A experiência que tirei ao codificar esse recurso no aplicativo foi que parsear MIDIs é um blues, não há padrão é tudo bagunçado tira sua sanidade fácil, fácil.

Amigo desenvolver se precisar parsear MIDIs boa sorte!!

Ain't It Funky Now! Vol. 1

Um dos meus discos favoritos de um dos meus guitarristas de Jazz favoritos!


Grant Green é um guitarrista com um fraseado inconfundível, depois da primeira audição, qualquer coisa que você ouvir por aí dele e mesmo não sabendo que é dele, vai suspeitar ser dele :) Uma das primeiras músicas que curti está num álbum chamado "The Final Comedown", se trata da música "Slight Fear and Terror".

Apesar de ser um guitarrista de Jazz, Grant Green também curtia Funky (veja funky, ok? em tempos estes é melhor usar o "y")... "Ain't It Funky Now!" (você deve saber a quem remete essa música/disco e o que torna o termo "funky", neste contexto até um pleonasmo...) traz esse lado mais funky, embora outros discos também tragam e este disco não ser considerado tão bom pelos críticos (embora não aconselhe consumir coisas com base em críticas, pois você pode perder certas preciosidades incompreendidas ao paladar da maioria)...

Na verdade não é um álbum que talvez possa entrar na discografia oficial, pois se trata mais de uma compilação. Sim, Grant Green era um guitarrista de Jazz funky que vez isso magistralmente ao longo de sua carreira.

"Ain't It Funky Now!" traz uma música que baixei na época em que estava conhecendo o som do cara e que estava incompleta... Sei que acabei gravando isso em um CD e perdi o arquivo MP3. Pronto, acabou que tinha gravada uma música que curtia mas não sabia o nome e ainda estava incompleta (não sei o porquê de não ter baixado ela de novo na época), o CD-R vagaba ainda descascou e perdi definitivamente qualquer referência a música, enfim, depois de muito ouvir e pesquisar acabei tendo a agradável surpresa de topar com ela nesse álbum, isso anos depois... :)

O nome da música? Bem fácil de guardar e sugerir, na verdade eram duas: "I don't want nobody to give me nothing (open up the door I'll get it myself)" e "Cold sweat".

Pois bem, te faço um desafio: ouça este album procurando não marcar o ritmo das músicas com as mãos, pés, cabeça... E nem cantarolar os grooves/temas ao longo do dia após tê-lo ouvido.

E sabe mais o que tenho para te dizer?

"You're" gonna groove!

;)

Uma linguagem para parseamento de buffers...

Eu sei "regex", "awk", mas é mal de cientista da computação... Queria meu próprio "Bufferstein".

Há 3 anos atrás pude proferir "It's alive, it's alive" com minha própria linguagem para parsing de buffers.

Não regulo muito e resolvi criar algo orientado à instruções, imagine um ASSEMBLY só que para buffers... Mas esse pseudo-ASSEMBLY é realmente alienígena!

É a BPL (Buffer Parsing Language), confesso que já fui mais criativo em acrônimos, e realmente é uma sigla bem genérica, hehe.

As instruções BPL (bem atômicas até certo ponto) são:


INSTRUÇÃOAÇÃO
auxCria um registrador auxiliar
setSeta todo conteúdo de um buffer
wlkIncrementa/decrementa ponteiro de deslocamento do buffer
ldbPõe um byte no offset atual de um buffer
bob"Ela é do tempo do bob!" :) Checa por início de buffer
eob"This is the end..." @:D Checa pelo final do buffer
jmpSalto condicional
lblAdiciona marcação de label no código, usado nos jumps
addIncrementa valor contido na posição de memória atual do buffer
subSimilar a add mas em termos de decremento
mulSimilar a sub mas em termos de multiplicação
divSimilar a mul mas em termos de divisão
aluResolve uma expressão lógica
varCria uma variável, ok, me chame de Herege ASSEMBLY people



Cada instrução informada tem suas particularidades quanto à passagem de parâmetros, caso queira saber mais, encontre os detalhes na documentação informada no final desse post.

Que tal exemplos:


  1. # Rot13 em C-Strings

  2. var byte %byte 0x0

  3. lbl ___DO_ROT13

  4. ldb %byte BUF

  5. jmp eq BUF 0x00 ___WALK_ON ___CONTINUE

  6. lbl ___CONTINUE

  7. sub %byte 13

  8. ldb BUF %byte

  9. lbl ___WALK_ON

  10. wlk > BUF

  11. eob %byte BUF

  12. jmp ne %byte 1 ___DO_ROT13 ___END_ROT13

  13. lbl ___END_ROT13


Um maior, que atesta minha loucura :P


  1. #

  2. # ``urldecoding.bpl'' ( Thu 08 May 2008 10:10:42 AM UTC )

  3. #

  4. # URL decoding sem suporte para Utf-8

  5. #

  6. var byte %result_flag 0

  7. aux %nibble_l 1

  8. aux %nibble_h 1

  9. aux %buf 8192

  10. lbl ___NEXT_HEX_BYTE

  11. eob %result_flag BUF

  12. jmp eq %result_flag 1 ___DECODING_END ___DO_NEXT_HEX_BYTE

  13. lbl ___DO_NEXT_HEX_BYTE

  14. jmp eq BUF "%" ___HEX_2_CHAR_BYTE ___NEXT_HEX_BYTE_CONTINUE

  15. lbl ___NEXT_HEX_BYTE_CONTINUE

  16. jmp eq BUF "+" ___PLUS_2_SPACE ___SIMPLE_ASSIGMENT

  17. lbl ___PLUS_2_SPACE

  18. ldb %buf " "

  19. jmp eq %buf " " ___POINTER_AHEAD ___POINTER_AHEAD # goto ;)

  20. lbl ___SIMPLE_ASSIGMENT

  21. ldb %buf BUF

  22. lbl ___POINTER_AHEAD

  23. wlk > %buf

  24. wlk > BUF

  25. jmp eq 1 1 ___NEXT_HEX_BYTE ___NEXT_HEX_BYTE

  26. lbl ___HEX_2_CHAR_BYTE

  27. wlk > BUF #[%]XX -> %[X]X

  28. ldb %nibble_h BUF

  29. jmp ge %nibble_h "0" ___IS_NUMBER_H ___NOT_NUMBER_H

  30. lbl ___IS_NUMBER_H

  31. jmp le %nibble_h "9" ___NUMBER_2_DEC_H ___NOT_NUMBER_H

  32. lbl ___NOT_NUMBER_H

  33. jmp ge %nibble_h "a" ___IS_LWR_ALPHA_H ___NOT_LWR_ALPHA_H

  34. lbl ___IS_LWR_ALPHA_H

  35. jmp le %nibble_h "f" ___LWR_ALPHA_2_DEC_H ___NOT_LWR_ALPHA_H

  36. lbl ___NOT_LWR_ALPHA_H

  37. jmp ge %nibble_h "A" ___IS_UPR_ALPHA_H ___NOT_UPR_ALPHA_H

  38. lbl ___IS_UPR_ALPHA_H

  39. jmp le %nibble_h "F" ___UPR_ALPHA_2_DEC_H ___NOT_UPR_ALPHA_H

  40. lbl ___NOT_UPR_ALPHA_H

  41. ldb %buf BUF

  42. wlk > BUF

  43. wlk > %buf

  44. jmp eq 1 1 ___NEXT_HEX_BYTE ___NEXT_HEX_BYTE

  45. lbl ___NUMBER_2_DEC_H

  46. sub %nibble_h 48

  47. jmp eq 1 1 ___NEXT_NIBBLE ___NEXT_NIBBLE

  48. lbl ___LWR_ALPHA_2_DEC_H

  49. sub %nibble_h 87

  50. jmp eq 1 1 ___NEXT_NIBBLE ___NEXT_NIBBLE

  51. lbl ___UPR_ALPHA_2_DEC_H

  52. sub %nibble_h 55

  53. lbl ___NEXT_NIBBLE

  54. mul %nibble_h 16

  55. wlk > BUF #%[X]X -> %X[X]

  56. ldb %nibble_l BUF

  57. jmp ge %nibble_l "0" ___IS_NUMBER_L ___NOT_NUMBER_L

  58. lbl ___IS_NUMBER_L

  59. jmp le %nibble_l "9" ___NUMBER_2_DEC_L ___NOT_NUMBER_L

  60. lbl ___NOT_NUMBER_L

  61. jmp ge %nibble_l "a" ___IS_LWR_ALPHA_L ___NOT_LWR_ALPHA_L

  62. lbl ___IS_LWR_ALPHA_L

  63. jmp le %nibble_l "f" ___LWR_ALPHA_2_DEC_L ___NOT_LWR_ALPHA_L

  64. lbl ___NOT_LWR_ALPHA_L

  65. jmp ge %nibble_l "A" ___IS_UPR_ALPHA_L ___NOT_UPR_ALPHA_L

  66. lbl ___IS_UPR_ALPHA_L

  67. jmp le %nibble_l "F" ___UPR_ALPHA_2_DEC_L ___NOT_UPR_ALPHA_L

  68. lbl ___NOT_UPR_ALPHA_L

  69. ldb %buf BUF

  70. wlk > BUF

  71. wlk > %buf

  72. jmp eq 1 1 ___NEXT_HEX_BYTE ___NEXT_HEX_BYTE

  73. lbl ___NUMBER_2_DEC_L

  74. sub %nibble_l 48

  75. jmp eq 1 1 ___ADJUST_L ___ADJUST_L

  76. lbl ___LWR_ALPHA_2_DEC_L

  77. sub %nibble_l 87

  78. jmp eq 1 1 ___ADJUST_L ___ADJUST_L

  79. lbl ___UPR_ALPHA_2_DEC_L

  80. sub %nibble_l 55

  81. jmp eq 1 1 ___ADJUST_L ___ADJUST_L

  82. lbl ___ADJUST_L

  83. add %nibble_h %nibble_l

  84. ldb %buf %nibble_h

  85. wlk > %buf

  86. wlk > BUF

  87. jmp eq 1 1 ___NEXT_HEX_BYTE ___NEXT_HEX_BYTE

  88. lbl ___DECODING_END

  89. set BUF "\0x00"

  90. lbl ___GET_BUF_REG_BEGIN

  91. wlk < %buf

  92. bob %result_flag %buf

  93. jmp ne %result_flag 1 ___GET_BUF_REG_BEGIN ___OVERWRITE_INPUT

  94. lbl ___OVERWRITE_INPUT

  95. ldb BUF %buf

  96. wlk > %buf

  97. wlk > BUF

  98. eob %result_flag %buf

  99. jmp eq %result_flag 1 ___DONE ___OVERWRITE_INPUT

  100. lbl ___DONE


É, criei um monstro.


"Inquirrível funquiciona. Está vivo, está vivo! MuAhhauahuahauh."
-- Dr. Bufferstein.


Pensei em criar a BPL enquanto desenvolvia um sniffer e esbarrei no problema de filtrar de forma geral dados vindos de protocolos layer7.

Meu sniffer no caso trabalha com uma linguagem bem específica que permite acesso aos campos dos protocolos de camada de rede e transporte, mas é impossível criar todos os campos para protocolos layer7 visto que à cada hora surge um novo (eita exagero)...

Nisso a BPL resolvia meu problema, entregando ao usuário a responsabilidade de criar seus próprios filtros para extração da informação layer7 desejada.

Fora que os usuários do sniffer podem criar seus próprios parsers e distribuir isso como funções de biblioteca.

Mas esse sniffer é outro post.

Documentação e compilador/interpretador em: BPL_pack.

Igor para Dr. Bufferstein:


"- Qual é o próximo plano mestre??"
"- Parsearemos o Mundo..."
"- Bom!"


Python impressions

Na linha do "me dê uma alavanca e um ponto de apoio que moverei o mundo"... "me dê um interpretador e um editor de textos que resolverei tudo" é o que um programador python deve sentir.

Não tinha tido muito contato com essa linguagem ainda, mas no trabalho tenho sido forçado usá-la e confesso que tinha uma idéia errada dela...

Certas coisas são muito fáceis, intuitivas e claras, contudo, a endentação é uma coisa que não ajuda muito. Não pelo fato de se endentar errado, mas a visualização do código principalmente se você não largar umas linhas em branco, contribui produzir uma maçaroca de código que franzirá tua testa ao ler de primeira algo escrito na linguagem.

Mandracarias bem escrotinhas diga-se de passagem. Falo principalmente de __init__.py... "Whatta fuck porra is that?!", tem tanta coisa que é assumida, será que não dá para se esforçar um pouco e deduzir/assumir isso também?

A interface de sockets é mais ou menos. Mexeram em certas coisas. Mexer na API clássica de sockets é a mesma coisa que mudar o formato de uma Strato, de uma Les Paul.... Enfim, eu sei lá.

O módulo de threads segue a "filosofia" Java de se lidar com a coisa: você não pode pausar, resumir ou cancelar um thread. Tisss... E aí?

Unicode blues.

Vantagens: coisas bem na cara... Se você já conhece C, as funções da libc que você encontra até em caixas de sapato... POSIX te diz algo? (bom, mas isso é outra história...) Se conhecer isso a introdução básica no site do python já vai ser bem informativa.

Outra fonte que indico é "dive into python", se trata de um livro com alguns extratos on-line e free.

Taí dois bons pontos de partida que me são bem úteis.

Minha impressão até o momento: Python é bom para resolver coisas que não posso ou não quero gastar tempo em cima. Em resumo bem prática, uma boa linguagem de apoio.

Led Zeppelin ao vivo

Recentemente fiquei ouvindo feito louco dois albums ótimos do Led Zeppelin:


"How The West Was Won"


"The Songs Remains the Same - The Soundtrack"

Foi a redescoberta do ouro, me senti com meus 13 anos de novo. Recaí de amores pelos dois, não parei de escutá-los. Me lembrei de como o Led Zeppelin é uma banda imbatível ao vivo (e impecável em estúdio).

Acho que nem os Beatles foram tão impecáveis na carreira como essa Banda (e olha que adoro os Beatles), por isso que à cada anúncio de reunião dos remanescentes, fico torcendo para que não gravem nada inédito e corram o risco de sujar uma carreira tão imaculada :P

"How The West Was Won" é formado por registros ao vivo encontrados pelo Jimmy Page enquanto procurava material para um DVD ao vivo da Banda, se não me engano aquele que tem um deserto na capa, que esqueci o nome agora.

No primeiro dos 3 CDs tem uma versão de "Over The Hills and Far Away" até melhor do que em "The Songs Remains the Same - The Soundtrack".

Mas no "Songs Remains" tem a música mais linda dos caras que é "The Rain Song" e uau que versão foda.

"How The West" dá a impressão de uma banda mais solta sem a responsabilidade de gravar um registro ao vivo definitivo, já no "Songs" dá para sentir um cuidado maior, mas que não engessa, pois estamos falando de uma banda que tocava ao vivo igual se estivesse apenas respirando.

Todos os dois albuns tem a mão do Eddie Krammer na gravação, não precisa dizer mais nada, né?

Se nunca ouviu esses CDs e se julga fã de rock, você deve, e deve feio... ouví-los!

:D

Teste qui-quadrado

Às vezes precisei utilizar aplicações do teste qui-quadrado em coisas que andei fazendo, mas sempre achei muito chato ter que ficar preenchendo aquelas planilhas em excel.

Acabei escrevendo um aplicativo para isso, no qual podia num único processamento realizar quantos testes qui quisesse e fora isso testar a homogeineidade das amostras, me gerando um log estatístico que julgo completo ou saídas "oráculo" do tipo "era o eu pensava", "não era o que eu pensava"

(In)felizmente nunca tive necessidade de usar isso no Windows então nunca migrei para ele o aplicativo. No link à seguir o download para o binário em Linux.


Chimera_pack.tar.gz.


Eu sou um fã confesso de compiladores e acho que não existe interface melhor com um computardor senão uma linguagem bem enxuta e específica para abordar o problema (óbvio, não vai existir um usuário final que se interessará aprender isso, 0.00001% talvez). Mas o importante é criar interfaces que mastiguem isso para o usuário, penso que isso cria boas bases, dando ao aplicativo maiores possibilidades de funcionamento. Pensar num aplicativo somente como uma tela com punhados de edits e botões é muito simplório e não acho que isso seja programar computadores, talvez programar "interfaces de usuário".

Filosofias à parte, esse aplicativo não é diferente do que penso, via uma linguagem expresso o teste Qui para a situação, vejamos uma clássica, o da moeda viciada:

"Uma moeda foi jogada n vezes e se conseguiu x vezes caras e y vezes coroas, testar se a moeda é viciada ou não"


  1. test "moeda_viciada" mode simple
  2. alfa 5% answer statistical

  3. {

  4. q = "A moeda é viciada?";

  5. p = 0.5;

  6. H0 = "A moeda não é viciada.";

  7. H1 = "A moeda é viciada.";

  8. o[] = {{"caras",60},{"coroas",40}};

  9. }

O nome das variáveis, procurei manter bem descritivas para quem entende do teste.
Para rodar o aplicativo é: ./chimera arquivo_com_o_teste.qui moeda_viciada
Caso queira uma saída html:./chimera arquivo_com_o_teste.qui moeda_viciada --html

Esse exemplo que mostrei é o teste simples, mas o aplicativo ainda aplica o Qui-2 com tabelas de contingência (geralmente gente da área de saúde usa muito esse tipo de qui-2), mas para isso caso se interesse baixe o aplicativo e leia o manual para saber como é.

Você que manja de estatística deve estar pensando mas não consigo aplicar correções?!


  1. test "moeda_viciada" mode simple
  2. alfa 5% answer statistical correction yates
  3. {

  4. q = "A moeda é viciada?";

  5. p = 0.5;

  6. H0 = "A moeda não é viciada.";

  7. H1 = "A moeda é viciada.";

  8. o[] = {{"caras",60},{"coroas",40}};

  9. }



Eu só implementei a correção de yates, realmente eu fiz isso para uma necessidade muito específica então nem me preocupei... Vou ver se disponibilizo os fontes, é um aplicativo mínimo e o parser ficou muito simples e fácil de aplicar extensões. Acho que qualquer pessoa interessada estende para o que quiser isso.

O link do aplicativo do post anterior se encontra aqui agora: Cherrry_pack.