Just a short, simple blog for Bob to share his thoughts.
04 August 2017 • by Bob • Batch Files, Scripting, FFMPEG, Audio Editing
I recently ran into a situation where I needed to adjust the pitch of an MP3 file for a song that I needed to learn. The problem was that song was recorded in a specific key, and I needed to play the song a half-step different. Of course, rehearsing in the original key and transposing on-the-fly is pretty trivial, but sometimes I prefer to learn a song in the key which I will be playing.
In the past I have always used a tool like Cakewalk Sonar to load the MP3 file, adjust the pitch, and then save out the adjusted audio. But I thought that was far too prosaic of an approach; I wanted a way to script the pitch change. This got me thinking about one of my favorite tools: FFmpeg.
I have mentioned FFmpeg in previous blogs, and it's one of my favorite tools; I use it almost every day for one purpose or other, and I have a large collection of batch files to automate various tasks. But unfortunately, I didn't have anything for adjusting audio pitch. That being said, I have done a lot with various FFmpeg audio and video filters, and after a little while of sifting through some of the various settings I came up with a way to easily change the pitch for an MP3 file. (And if I ever need to automate a whole directory of MP3 files, it would be simple to update this script with a loop.)
Here's the secret to the way this works - there are two audio filters that I am using:
So the trick is to use these two filters inversely; in other words:
With that in mind, I pulled out one of my favorite math constants: 2^(1/12), which is roughly 1.0594630943592952645618252949463. You might recall from some of my other blogs that this is the value by which every pitch in Equal Temperament is derived; in other words, that value is used to create every note in the chromatic scale which is used throughout the planet.
Taking that into account, I looked at the filter settings that were possible for use with FFmpeg:
The math is a little weird, I'll admit - but it's pretty straight-forward. And here's the great part for you: I've already done the math, and I've written a batch file which defines a set of constants that can be used in batch files to script the raising or lowering the pitch of an MP3 file.
Here's the code for the batch file:
@echo off set TMPFILE1=InputFile.mp3 set TMPFILE2=OutputFile.mp3 set RAISE_PITCH_01=asetrate=r=46722.3224612449211671764955071340,atempo=0.94387431268169349664191315666753 set RAISE_PITCH_02=asetrate=r=49500.5763304433484812188074908520,atempo=0.89089871814033930474022620559051 set RAISE_PITCH_03=asetrate=r=52444.0337716199990422417487017170,atempo=0.84089641525371454303112547623321 set RAISE_PITCH_04=asetrate=r=55562.5183003639065662339877809700,atempo=0.79370052598409973737585281963615 set RAISE_PITCH_05=asetrate=r=58866.4375688985154890396859602340,atempo=0.74915353843834074939964036601490 set RAISE_PITCH_06=asetrate=r=62366.8181006534916521544727376480,atempo=0.70710678118654752440084436210485 set RAISE_PITCH_07=asetrate=r=66075.3420902616540970482802825140,atempo=0.66741992708501718241541594059223 set RAISE_PITCH_08=asetrate=r=70004.3863917975968365502186919090,atempo=0.62996052494743658238360530363911 set RAISE_PITCH_09=asetrate=r=74167.0638253776226953452670037700,atempo=0.59460355750136053335874998528024 set RAISE_PITCH_10=asetrate=r=78577.2669399779266780879513330830,atempo=0.56123102415468649071676652483959 set RAISE_PITCH_11=asetrate=r=83249.7143785253664038167404180770,atempo=0.52973154717964763228091264747317 set RAISE_PITCH_12=asetrate=r=88200.0000000000000000000000000000,atempo=0.50000000000000000000000000000000 set LOWER_PITCH_01=asetrate=r=41624.8571892626832019083702090380,atempo=1.05946309435929526456182529494630 set LOWER_PITCH_02=asetrate=r=39288.6334699889633390439756665420,atempo=1.12246204830937298143353304967920 set LOWER_PITCH_03=asetrate=r=37083.5319126888113476726335018850,atempo=1.18920711500272106671749997056050 set LOWER_PITCH_04=asetrate=r=35002.1931958987984182751093459540,atempo=1.25992104989487316476721060727820 set LOWER_PITCH_05=asetrate=r=33037.6710451308270485241401412570,atempo=1.33483985417003436483083188118450 set LOWER_PITCH_06=asetrate=r=31183.4090503267458260772363688240,atempo=1.41421356237309504880168872420970 set LOWER_PITCH_07=asetrate=r=29433.2187844492577445198429801170,atempo=1.49830707687668149879928073202980 set LOWER_PITCH_08=asetrate=r=27781.2591501819532831169938904850,atempo=1.58740105196819947475170563927230 set LOWER_PITCH_09=asetrate=r=26222.0168858099995211208743508580,atempo=1.68179283050742908606225095246640 set LOWER_PITCH_10=asetrate=r=24750.2881652216742406094037454260,atempo=1.78179743628067860948045241118100 set LOWER_PITCH_11=asetrate=r=23361.1612306224605835882477535670,atempo=1.88774862536338699328382631333510 set LOWER_PITCH_12=asetrate=r=22050.0000000000000000000000000000,atempo=2.00000000000000000000000000000000 ffmpeg -y -i "%TMPFILE1%" -af "%RAISE_PITCH_01%" "%TMPFILE2%"
The only parts that you need to configure are:
There are, of course, hundreds of other parameters which you can pass to FFmpeg in order to customize how FFmpeg processes the audio, but those are way out of scope for this blog.
With that in mind, that's it for now; have fun!
19 July 2017 • by bob • Family
I stumbled across the following article recently, which briefly discusses an issue that our family has struggled with:
How to Forgive When It's Hard to Forget
Without going into too much detail, someone in our family hurt my children; and by that I mean this person really hurt my children - in life-altering ways. When someone injures your children, you want that person to be punished; you want them to suffer for the years of pain your children have had to endure. And yet for reasons I cannot explain, this person has never faced justice. We cut this person out of our lives as you would with any other cancer, but unfortunately that is the most that we can do.
That being said, our family is predominantly populated with Christians who want everyone and everything to be "forgiven," and for all of us to get along as one big, happy family. However, since the person who caused all of this pain and suffering has never changed, any semblance of restoration is probably never going to happen, for reasons that should be obvious to anyone who loves their children. But seeing as how it was only my children who were hurt, my wife and I have received countless comments from other family members asking whether we have "forgiven" the pernicious person who is the source of our family troubles. We have assured everyone that we have, which then leads to the questions about why can't our "lives go back to the way they were before all of this started."
First of all, the way our lives were before "all of this started" does not mean that the guilty party wasn't hurting other people; it was just happening to people outside our immediate family, and being swept under the rug because people chose not to see that it was happening. But that is a different problem for a different day.
The problem that currently faces our family is: what does it mean to forgive someone?
For some of our family members, "forgiveness" means a complete and total restoration. But that is a totally naïve sentiment, and it completely ignores or trivializes the suffering of those whose lives were damaged. My wife and I have tried to explain time and again that we have "forgiven" the person who wounded our family, but we have no desire to rekindle a relationship with the guilty party. To other family members this looks like "unforgiveness," whereas to me this looks like "common sense." One should not willingly subject their loved ones to a harmful person in the name of "forgiveness."
This is why I enjoyed the article that I mentioned earlier; in that piece, Dr. Cloud did a great job of summarizing the different parts of a restoration process, which I will paraphrase and adapt to our family's situation:
Forgiveness: This is letting go of what you believe is your right to punish someone for how they hurt you. My wife and I have done so; it was difficult, but holding onto unforgiveness is more harmful to yourself than it is to others. Or as a popular idiom states, "Holding on to unforgiveness is like drinking poison and expecting the other person to die."
Reconciliation: This is when the other person apologizes and accepts forgiveness; this has not happened within our family. In fact, the guilty party is still asserting that he or she has never done anything wrong, and recently demanded an apology for the years that he or she was denied access to our family. With this person's attitudes in mind, any hope of reconciliation is currently impossible.
Trust: This is when you allow a person whom you have forgiven back into your life. This may be a long, slow process, because it involves re-establishing your confidence that the person who hurt you will not do so again. In our family's situation, the person responsible for all of the suffering still insists no wrong-doing, so there can be no reasonable assumption that this person will not hurt someone again. Perhaps he or she will not wound someone in the same way as before, but still - I do not trust this person around my spouse or children.
Bringing this discussion to a close, we need to make a clear distinction between "forgiveness" and "reconciliation" in our lives. When we confuse these actions, we may subject ourselves to further injury. We certainly need to forgive those who harm us, but it is up to the other person to reconcile the situation and to re-establish trust. If the other person is unwilling to do so, then you are far better off without them in your life.
By the way, the following book by Jerry Cook is a good resource for anyone who is faced with difficult life situations and questions about forgiveness:
Love, Acceptance and Forgiveness: Being Christian in a Non-Christian World
UPDATE:
This blog originally pointed to the article How to Extend Forgiveness and Set a Boundary, but that article has been removed from Dr. Cloud's website and the Internet Archive does not have a cached version, so I replaced it with the article you now see.
14 July 2017 • by Bob • Ponderings, History
I was going through some boxes recently, where I discovered the following book...
My parents gave me this book in the early 1970s when I was eight years old, and I carried that book everywhere. Way back then, my life's ambition was to become a paleontologist, and this book had some excellent chapters on dinosaurs which I read over and over again.
However, my copy of this book was definitely showing its 45 years of age; it's binding had worn away to nothing, countless pages were torn... even though I didn't check, I'm pretty sure that some pages were missing. There is no doubt - this was a well-loved volume of knowledge back in its day; but now it was little more than a shadow of its former self, and a sad relic of days gone by.
Still, though, it's amazing the history through which this book persisted in my personal (albeit negligent) care... when I received this book as a gift, Richard Nixon was President of the United States, the average price for a gallon of gasoline was 39 cents, the United States was still embroiled in the waning years of the Vietnam War, Pink Floyd released Dark Side of the Moon, and the biggest single of the year was "Tie a Yellow Ribbon" by Tony Orlando and Dawn.
Nevertheless, this compendium of natural history knowledge had outlived its usefulness several years ago, and it was time to say goodbye. So with a heavy heart I unceremoniously dispatched my once-faithful companion to the recycle bin, where I hope that some part of it might wind up as another book which will spark another child's imagination in decades to come. Or perhaps that's just what I tell myself in order to feel a little less guilty...
24 June 2017 • by bob • Bicycling, Arizona
During today's 32-mile ride through the deserts on the east side of Tucson, I probably should have called it quits when the temperature hit 120 degrees on my GPS... but then again, I was out in the desert with nowhere to stop, so my choices were: 1) keep riding, or 2) die. Or as Winston Churchill famously remarked, "If you're going through hell, keep going."
Originally this was supposed to be my usual 40-mile Saturday ride, but I decided right before my departure to drop the 8-mile loop through Saguaro National Park. (Which in hindsight was undoubtedly a really good idea.) On a positive note, there appeared to be no other cyclists riding today, so I had the roads all to myself.
(PS - I didn't get a photo for when the temperature hit 133 degrees on my GPS because my cell phone shut down due to the excessive heat. Of course, my lack of cell phone meant that I was also unable to abort the ride and call my wife to come find me.)
20 June 2017 • by Bob • Guitar, Music
I had a song continuously running through my head, and as I have done before, I decided to transcribe it in order to get it unstuck and move on with life... Tonight's song was "Unchained" by Van Halen, which was a perennial favorite of mine to play live back in the early 1980s. I used Guitar Pro to do the transcription and playback, and while the transcription isn't 100% it's pretty good for an hour's worth of work. Plus, I think I did a pretty decent job of dialing in Eddie's tone when compared to the original.
Note: I didn't transcribe the guitar solo section because the intro, verses, bridges, and choruses were enough to get the song out of my system.
But you never know, I might come back to this later...
UPDATE:
A few years after my original post, I looked over my transcription, and what I called "Bridges" probably should have been called "Pre-Choruses." Oh well... it's a free transcription, so deal with it.
15 June 2017 • by Bob • CPP, Programming
Trying to get someone else's 20-year-old C++ code to compile is like trying to translate hieroglyphics without the use of the Rosetta Stone...
"Safe strings to prevent buffer overruns? Bah! Who needs 'em..."
UPDATE: True story - the original C++ code which was the impetus behind this blog post was written sometime around the release of Visual Studio 5 or 6, so the way that I eventually managed to get this code to compile on an up-to-date version of Visual Studio was to do the following: I set up a virtual machine in Hyper-V running Windows XP, installed Visual Studio 6.0, and compiled the code. Once I had it compiling with no errors, I kept updating the version of Visual Studio and recompiling; e.g. VS.NET, VS2003, VS2005, VS2008, VS2010, VS2012, VS2013, and finally VS2015, (which was good enough for what I needed to accomplish). As I upgraded each version of Visual Studio, I fixed whatever errors were introduced on a version-by-version basis. A few hours later and all the errors were gone, and the original program worked great.
13 June 2017 • by bob • Humor, Technology
Wait... Apple is working on a self-driving car? Have they even SEEN Apple Maps?
An Apple car would drive you right off a bridge, and as your car settled to the bottom of a river Siri would cheerfully say, "You've arrived at your destination."
06 June 2017 • by bob • History, Humor
Given the increasingly-ridiculous levels of political correctness and unnecessary inclinations towards white guilt, here is a bit of alternative history for today, which examines how the contemporary mainstream media might have handled the D-Day invasion if it had happened in the present:
7:30am, Tuesday, June 6, 1944
From various World News Services:
This just in - American and Allied forces, undoubtedly with imperialist ambitions, are currently attacking hundreds of undermanned and outgunned German soldiers, who are now desperately fighting for their lives amidst an onslaught of unprovoked Anglo-Saxon aggression. Just four years earlier, these same German forces successfully liberated France from centuries of colonial and imperial oppression, and yet they now find their comrades senselessly slaughtered on the beaches of Normandy while trying to defend the innocent people of France from foreign invaders.
Joseph Goebbels, the distinguished spokesman for the widely-popular German National Socialist Party, condemned the heinous atrocities of the invaders by stating, "This is a sad day for Europe. German sovereignty has been deliberately and ruthlessly challenged in a cowardly, pre-dawn surprise attack by those who wish to see Europe returned to the Dark Ages. After we have forced these intruders back into the sea from whence they came, history will remember this as a triumph for humanity, and henceforth remember this day as 'Deutschland-Day!'"
General Eisenhower, the duplicitous 'commander' of the invading forces, could not be reached for comment.
03 June 2017 • by bob • Rants, Politics
In response to comedienne Kathy Griffin's recent political stupidity, someone close to me (who shall remain nameless) posted the following image to Facebook with the caption that "Double Standards Abound:"
Now I will not attempt - even for a second - to defend any of the Drumpf's ludicrous statements; he is a never-ending stream of verbal diarrhea. However, I want you to imagine if four years ago some comedian had posed with the severed head of Obama... that guilty party would still be serving a jail sentence for a hate crime, and there's your real double-standard. Or what would have happened if the Drumpf had posed with the severed head of Hillary Clinton during the presidential race? Can you imagine the uproar that would have caused?
Make no mistake - the Drumpf is an idiot, but what Kathy Griffin did exceeds the mere assertion that she "went a little too far." If we take the Bette Davis quote from that image at face value and we assume that Ms. Griffin was just "giving her opinion" by her actions, then think about what that really means.
I'm sorry, but espousing the death of a sitting president is unconscionable, even if that president is hypocritical buffoon and you cannot stand him; you cannot defend the indefensible simply because you happen to loathe the target of their hatred.
24 May 2017 • by bob • Humor, Ponderings, Marriage
No woman in her right mind would want to be called a "Cow," and yet so many women shop at a place called the "Dress Barn."
This makes no sense to me...